diff -u --recursive --new-file v2.1.50/linux/CREDITS linux/CREDITS --- v2.1.50/linux/CREDITS Mon Aug 11 14:47:04 1997 +++ linux/CREDITS Sat Aug 16 09:51:46 1997 @@ -586,11 +586,9 @@ S: Germany N: Richard Henderson -E: rth@tamu.edu +E: richard@gnu.ai.mit.edu +E: rth@cygnus.com D: Alpha/ELF, gcc, binutils, and glibc -S: 304 E. North Ave. -S: Bryan, Texas 77801-3431 -S: USA N: Sebastian Hetze E: she@lunetix.de @@ -929,6 +927,13 @@ S: Canberra ACT 0200 S: AUSTRALIA +N: Pavel Machek +E: pavel@atrey.karlin.mff.cuni.cz +D: Softcursor for vga, hypertech cdrom support, vcsa bugfix +S: Volkova 1131 +S: 198 00 Praha 9 +S: Czech Republic + N: James B. MacLean E: macleajb@ednet.ns.ca W: http://www.ednet.ns.ca/~macleajb/dosemu.html @@ -1156,7 +1161,7 @@ D: improved memory detection code. N: Avery Pennarun -E: apenwarr@foxnet.net +E: apenwarr@bond.net D: ARCnet driver D: "make xconfig" improvements D: Various minor hacking @@ -1654,6 +1659,14 @@ S: Oosterstraat 23 S: 2611 TT Delft S: The Netherlands + +N: David Woodhouse +E: dwmw2@cam.ac.uk +D: Extensive ARCnet rewrite +D: ARCnet COM20020, COM90xx IO-MAP drivers +S: Robinson College, Grange Road +S: Cambridge. CB3 9AN +S: England N: Frank Xia E: qx@math.columbia.edu diff -u --recursive --new-file v2.1.50/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.50/linux/Documentation/Configure.help Thu Aug 14 20:49:16 1997 +++ linux/Documentation/Configure.help Mon Aug 18 15:21:39 1997 @@ -14,11 +14,17 @@ # has a French translation of the whole kernel, including # Configure.help. This is maintained by David Bourgin # (dbourgin@wsc.com). +# - ftp://ftp-pavia1.linux.it/pub/linux/Configure.help +# is a work-in-progress effort of the Italian translation team, +# currently only for the 2.0 version of this file, maintained +# by rubini@linux.it. # # Information about what a kernel is, what it does, how to patch and # compile it and much more is contained in the Kernel-HOWTO, available # via ftp (user: anonymous) from sunsite.unc.edu in the directory -# /pub/Linux/docs/HOWTO. +# /pub/Linux/docs/HOWTO. Before you start compiling, make sure that +# you have the necessary versions of all programs; they are listed +# in Documentation/Changes. # # Format of this file: descriptionvariablehelptext. # If the question being documented is of type "choice", we list only @@ -143,17 +149,18 @@ from the machine to itself. Most users will answer N here. Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support -CONFIG_BLK_DEV_IDE +CONFIG_BLK_DEV_IDE This will use the full-featured IDE driver to control up to four IDE - interfaces, for a combination of up to eight IDE - disk/cdrom/tape/floppy drives. Useful information about large - (>540MB) IDE disks, soundcard IDE ports, module support, and other - topics, is all contained in Documentation/ide.txt. If you have one - or more IDE drives, say Y here. If your system has no IDE drives, or - if memory requirements are really tight, you could say N here, and - select the Old harddisk driver instead to save about 13kB of memory - in the kernel. To fine-tune IDE drive/interface parameters for - improved performance, look for the hdparm package at + interfaces, each being able to serve a "master" and a "slave" + device, for a combination of up to eight IDE disk/cdrom/tape/floppy + drives. Useful information about large (>540MB) IDE disks, + soundcard IDE ports, module support, and other topics, is all + contained in Documentation/ide.txt. If you have one or more IDE + drives, say Y here. If your system has no IDE drives, or if memory + requirements are really tight, you could say N here, and select the + Old harddisk driver instead to save about 13kB of memory in the + kernel. To fine-tune IDE drive/interface parameters for improved + performance, look for the hdparm package at sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/ Old harddisk (MFM/RLL/IDE) driver @@ -326,12 +333,15 @@ of the Holtek card, and permits faster I/O speeds to be set as well. See the Documentation/ide.txt and ht6560b.c files for more info. -PROMISE DC4030 support (EXPERIMENTAL) +PROMISE DC4030 support (EXPERIMENTAL) CONFIG_BLK_DEV_PROMISE - This driver provides support for the second port and cache of - Promise IDE interfaces, e.g. DC4030 and DC5030. It is enabled at - kernel runtime using the "ide0=dc4030" kernel boot parameter. See - the file drivers/block/promise.c file for more info. + This driver provides support for the secondary IDE interface and + cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver + is known to incur timeouts/retries during heavy I/O to drives + attached to the secondary interface. CDROM and TAPE devices are not + supported yet. This driver is enabled at runtime using the + "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt + and drivers/block/promise.c files for more info. OPTi 82C621 support (EXPERIMENTAL) CONFIG_BLK_DEV_OPTI621 @@ -359,16 +369,6 @@ I/O speeds to be set as well. See the Documentation/ide.txt and ali14xx.c files for more info. -PROMISE DC4030 support (EXPERIMENTAL) -CONFIG_BLK_DEV_PROMISE - This driver is enabled at runtime using the "ide0=dc4030" kernel - boot parameter. It enables support for the secondary IDE interface - of the chipset, and takes advantage of the caching features of the - card. This driver is known to incur timeouts/retries during heavy - I/O to drives attached to the secondary interface. CDROM and TAPE - devices are not supported yet. See the Documentation/ide.txt and - promise.c files for more info. - XT harddisk support CONFIG_BLK_DEV_XD Very old 8 bit hard disk controllers used in the IBM XT computer. To @@ -384,9 +384,9 @@ removable media devices you can use this driver. Answer Y to build the driver into the kernel, or M if you would like to build it as a loadable module. The module will be called ez.o. Read the file - linux/Documentation/ez.txt. If you have several different devices - that will share a common parallel port you should build them all as - modules. + linux/Documentation/ez.txt. It is possible to use several devices + with a single common parallel port (e.g. printer and EZ135); it is + safe to compile both drivers into the kernel. Multiple devices driver support CONFIG_BLK_DEV_MD @@ -425,8 +425,8 @@ kernel that runs on these, say Y here. For details about Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at http://lena.fnet.fr/ (To browse the WWW, you need to - have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). + have access to a machine on the Internet that has a program like + lynx or netscape). Support for Mips Magnum 3000 CONFIG_MIPS_MAGNUM_3000 @@ -434,25 +434,23 @@ details about Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at http://lena.fnet.fr/ (To browse the WWW, you need to have access to a machine on the Internet that has - one of the programs lynx, netscape or Mosaic). + a program like lynx or netscape). Support for Mips Magnum 4000 CONFIG_MIPS_MAGNUM_4000 This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux - on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://lena.fnet.fr/ (To browse the WWW, you need to - have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + http://lena.fnet.fr/ (To browse the WWW, you need to have access to + a machine on the Internet that has a program like lynx or netscape). Support for Olivetti M700 CONFIG_OLIVETTI_M700 This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux - on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://lena.fnet.fr/ (To browse the WWW, you need to - have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + http://lena.fnet.fr/ (To browse the WWW, you need to have access to + a machine on the Internet that has a program like lynx or netscape). Support for Deskstation Tyne CONFIG_DESKSTATION_TYNE @@ -461,27 +459,26 @@ problems. For details about Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at http://lena.fnet.fr/ (To browse the WWW, you need to have access to a machine on the Internet that - has one of the programs lynx, netscape or Mosaic). + has a program like lynx or netscape). Support for Acer PICA 1 chipset CONFIG_ACER_PICA_61 This is a machine with a R4400 134/150 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about - Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the - WWW at http://lena.fnet.fr/ (To browse the WWW, you need to have - access to a machine on the Internet that has one of the programs - lynx, netscape or Mosaic). + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + http://lena.fnet.fr/ (To browse the WWW, you need to have access to + a machine on the Internet that has a program like lynx or + netscape). Support for DECstation CONFIG_DECSTATION The DECStation 3100 (with a MIPS R2000 series CPU) and DECStation 5000/xxx (MIPS R3000 series CPU) are also sometimes labeled PMAX. They often run the Ultrix operating system. To compile a Linux - kernel that runs on these, say Y here. For details about Linux - on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://lena.fnet.fr/ (To browse the WWW, you need to - have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + http://lena.fnet.fr/ (To browse the WWW, you need to have access to + a machine on the Internet that has a program like lynx or netscape). CPU type CONFIG_CPU_R3000 @@ -538,28 +535,35 @@ SYN flood protection CONFIG_SYN_COOKIES - Normal TCP/IP networking is open to an attack known as SYN flooding. - This attack prevents legitimate users from being able to connect to - your computer and requires very little work for the attacker. + Normal TCP/IP networking is open to an attack known as "SYN flooding". + This denial-of-service attack prevents legitimate remote users from + being able to connect to your computer and requires very little work + from the attacker, who can operate from anywhere on the internet. SYN cookies provide protection against this type of attack. With - this option turned on the TCP/IP stack will use a cryptographic + this option turned on, the TCP/IP stack will use a cryptographic challenge protocol known as SYN cookies to enable legitimate users to continue to connect, even when your machine is under attack. - Note that SYN cookies aren't enabled per default, you need to add - echo 1 >/proc/sys/net/ipv4/tcp_syncookies to one of your startup scripts - (e.g. /etc/rc.local or /etc/rc.d/rc.local). + There is no need for the legitimate users to change their TCP/IP + software; SYN cookies work transparently to them. For technical + information about syn cookies, check out + ftp://koobera.math.uic.edu/pub/docs/syncookies-archive. + If you say Y here, note that SYN cookies aren't enabled by default: + you need to add the command + echo 1 >/proc/sys/net/ipv4/tcp_syncookies + to one of your startup scripts (e.g. /etc/rc.local or + /etc/rc.d/rc.local) in addition. + If unsure, say Y. Socket Security API Support (EXPERIMENTAL) CONFIG_NET_SECURITY - Enable use of the socket security API. Note that Linux does not include - any security protocols currently and that this option only really supports - security on IPv4 links at the moment. - -Socket Security API Support (EXPERIMENTAL) -CONFIG_NET_SECURITY - Enable use of the socket security API. Note that Linux does not include - any security protocols currently and that this option only really supports - security on IPv4 links at the moment. + Enable use of the socket security API. This option only really + supports security (via encryption of all traffic) over IPv4 links, + and then only if you add a security protocol which is also supported + at the other end of the link; Linux itself does not include any + security protocols, but you can use the enskip package at + ftp.tik.ee.ethz.ch/pub/packages/skip/. That package also contains + documentation of the API to be used for secure sockets. If unsure, + say N. Sun floppy controller support CONFIG_BLK_DEV_SUNFD @@ -571,14 +575,16 @@ Find out what type of Alpha motherboard you have. You will probably want to read the Linux/Alpha homepage on the WWW at http://www.azstarnet.com/~axplinux/ (To browse the WWW, you need to - have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). For this question, it suffices - to give a unique prefix of the option you want to choose. The - choices: + have access to a machine on the Internet that has a program like + lynx or netscape). For this question, it suffices to give a unique + prefix of the option you want to choose. The choices: ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400) - and XL (a.k.a. "Windows NT Dream Machine" :-) AlphaStations. - These usually come with a TGA graphics adapter, so you'll want to - say Y to "TGA Console support", below, if you have one of these. + AlphaStations. These usually come with a TGA graphics adapter, + so you'll want to say Y to "TGA Console support", below, if you + have one of these. + ** Alpha-XL: A.k.a. "Windows NT Dream Machine" :-) These usually + come with a TGA graphics adapter, so you'll want to say Y to "TGA + Console support", below, if you have one of these. ** Jensen: a.k.a. DEC 2000 a.k.a. DECpc AXP 150, the oldest Alpha PC; it sports an EISA bus. The boot process on Jensen machines is difficult (no booting from floppies, MILO doesn't work). You need @@ -593,15 +599,9 @@ ** EB66: "Evaluation Board" ** EB66+: "Evaluation Board" ### -### Add info about Platform2000, EB164 +### Add info about Platform2000, EB164, etc. ### -Is it really a true XL -CONFIG_ALPHA_XL - If your Avanti Machine is of type XL (a.k.a. "Windows NT Dream - Machine") (as opposed to Mustang (AS200), M3 (AS250) or Avanti - (AS400)), say Y, otherwise N. - Using SRM as bootloader CONFIG_ALPHA_SRM There are two different types of booting firmware on Alphas: SRM, @@ -619,8 +619,8 @@ N. Details about the Linux/Alpha booting process are contained in the Linux/Alpha FAQ, accessible on the WWW from http://www.azstarnet.com/~axplinux/ (To browse the WWW, you need to - have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). + have access to a machine on the Internet that has a program like + lynx or netscape). Non-standard serial port support CONFIG_SERIAL_NONSTANDARD @@ -635,7 +635,7 @@ can say N here. Extended dumb serial driver options -CONFIG_SERIAL_EXTENDED +CONFIG_SERIAL_EXTENDED If you wish to use any non-standard features of the standard "dumb" driver, say Y here. This includes HUB6 support, shared serial interrupts, special multiport support, support for more than the @@ -750,15 +750,15 @@ executables are distributed solely in ELF format. You definitely want to say Y here. Information about ELF is on the WWW at http://www.sjc.ox.ac.uk/users/barlow/elf-howto.html (To browse the - WWW, you need to have access to a machine on the Internet that has - one of the programs lynx, netscape or Mosaic). If you find that - after upgrading to Linux kernel 1.3 and saying Y here, you still - can't run any ELF binaries (they just crash), then you'll have to - install the newest ELF runtime libraries, including ld.so (check the - file Documentation/Changes for location and latest version). If you - want to compile this as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read Documentation/modules.txt. The module will be called + WWW, you need to have access to a machine on the Internet that has a + programs like lynx or netscape). If you find that after upgrading + to Linux kernel 1.3 and saying Y here, you still can't run any ELF + binaries (they just crash), then you'll have to install the newest + ELF runtime libraries, including ld.so (check the file + Documentation/Changes for location and latest version). If you want + to compile this as a module ( = code which can be inserted in and + removed from the running kernel whenever you want), say M here and + read Documentation/modules.txt. The module will be called binfmt_elf.o. Saying M or N here is dangerous because some crucial programs on your system might be in ELF format. @@ -810,18 +810,32 @@ will be called binfmt_java.o. If you don't know what to answer at this point then answer Y. +Kernel support for Linux/Intel ELF binaries +CONFIG_BINFMT_EM86 + Say Y here if you want to be able to execute Linux/Intel ELF + binaries just like native Alpha binaries on your machine. For this + to work, you need to have the emulator /usr/bin/em86 in place. You + may answer M to compile the emulation support as a module and later + load the module when you want to use a Linux/Intel binary. The + module will be called binfmt_em86.o. If unsure, say Y. + Kernel support for MISC binaries CONFIG_BINFMT_MISC This enables the possibility to plug wrapper-driven binary formats into the kernel. You will like this especially when you use programs - that need an interpreter to run like Java, Python or Emacs-Lisp. And - you don't need CONFIG_BINFMT_JAVA or CONFIG_BINFMT_EM86, as this is - a more general feature. - You can do other nice things, too. Read Documentation/binfmt_misc.txt - to learn how to use this feature. - You must enable CONFIG_PROC_FS to use this part of the kernel. + that need an interpreter to run like Java, Python or + Emacs-Lisp. Once you have registered such a binary class with the + kernel, you can start such a program simply by typing in its name; + Linux will feed it to the correct interpreter. If you say Y here, + you won't need "Kernel support for JAVA binaries" + (CONFIG_BINFMT_JAVA) or "Kernel support for Linux/Intel ELF + binaries" (CONFIG_BINFMT_EM86), as this is a more general solution. + You can do other nice things, too. Read + Documentation/binfmt_misc.txt to learn how to use this feature. + You must enable the "proc filesystem support" (CONFIG_PROC_FS) to + use this part of the kernel. You may answer M for module support and later load the module when - you have use for it. + you have use for it. If you don't know what to answer at this point, say Y. Processor type @@ -850,6 +864,29 @@ for more information about the Video mode selection support. If unsure, say N. +Parallel-port support +CONFIG_PARPORT + If you want to use devices connected to your parallel port (the + connector at the computers with 25 holes), e.g. printer, Zip drive, + PLIP link etc., then you need to enable this option; please read + Documentation/parport.txt and drivers/misc/BUGS-parport. It + is possible to share a single parallel port among several devices + and it is safe to compile all the corresponding drivers into the + kernel. If you want to compile parallel port support as a module ( = + code which can be inserted in and removed from the running kernel + whenever you want), say M here and read + Documentation/modules.txt. The module will be called parport.o. If + you have more than one parallel port and want to specify which port + and IRQ to use by this driver at module load time, read + Documentation/networking/net-modules.txt. + +PC-style hardware +CONFIG_PARPORT_PC + You should enable this option if you have a PC-style parallel + port. All IBM PC compatible computers and some Alphas have PC-style + parallel ports. This driver is also available as a module which + will be called parport_pc.o. + Compile the kernel into the ELF object format CONFIG_ELF_KERNEL ELF (Executable and Linkable Format) is a format for libraries and @@ -876,14 +913,8 @@ Plug and Play support allows the kernel to automatically configure some peripheral devices. Say Y to enable PnP. -Parallel-port support +Auto-probe for parallel devices CONFIG_PNP_PARPORT - If you want to use devices connected to your parallel port (printer, - Zip driver, PLIP link, ...) then you should enable this option and - read Documentation/parport.txt. - -Autoprobe for parallel device IDs -CONFIG_PNP_PARPORT_AUTOPROBE Some IEEE-1284 conformant parallel-port devices can identify themselves when requested. If this option is enabled the kernel will probe to see what devices are connected at boot time. @@ -942,9 +973,10 @@ here, the kernel's internal ARP cache will never grow to more than 256 entries (the oldest entries are expired in a LIFO manner) and communication will be attempted with an external ARP daemon, arpd. - This code is still experimental. If you do say Y here, you - should obtain a copy of arpd from - http://www.loran.com/~layes/arpd/index.html. If unsure, say N. + This code is still experimental. If you do say Y here, you should + obtain a copy of arpd from http://www.loran.com/~layes/arpd/index.html, + and you should say Y to "Kernel/User network link driver", below. + If unsure, say N. TCP/IP networking CONFIG_INET @@ -957,9 +989,8 @@ necessary if you want to use the full power of term (term is a program which gives you almost full Internet connectivity if you have a regular dial up shell account on some Internet connected Unix - computer. Read the Term-HOWTO, available via ftp (user: anonymous) - on sunsite.unc.edu:/pub/Linux/docs/HOWTO). Short answer: - say Y. + computer. Read http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html). + Short answer: say Y. IP: multicasting CONFIG_IP_MULTICAST @@ -971,9 +1002,9 @@ of the internet which carries audio and video broadcasts. More information about the MBONE is on the WWW at http://www.best.com/~prince/techinfo/mbone.html (to browse the WWW, - you need to have access to a machine on the Internet that has one of - the programs lynx, netscape or Mosaic). Information about the - multicast capabilities of the various network cards is contained in + you need to have access to a machine on the Internet that has a + program like lynx or netscape). Information about the multicast + capabilities of the various network cards is contained in drivers/net/README.multicast. For most people, it's safe to say N. IP: optimize as router not host @@ -983,6 +1014,11 @@ packets to another host this is however a loss. This parameter turns off copy and checksum from devices. It may make other changes in the future. + Note that your box can only act as a router if you say Y to "/proc + filesystem support" below and you enable IP forwarding in your + kernel; you can do this from within a boot-time script like so: + echo "1" > /proc/sys/net/ipv4/ip_forwarding + after the /proc filesystem has been mounted. If unsure, say N here. IP: firewalling CONFIG_IP_FIREWALL @@ -993,8 +1029,13 @@ sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you will need the ipfwadm tool (available via ftp (user: anonymous) from ftp.xos.nl/pub/linux/ipfwadm/) to allow selective blocking of - internet traffic based on type, origin and destination. You need to - say Y to "IP firewalling" in order to be able to use IP masquerading + internet traffic based on type, origin and destination. The + firewalling code will only work if you say Y to "/proc filesystem + support" below and IP forwarding is enabled in your kernel; do this + from within a boot-time script like so: + echo "1" > /proc/sys/net/ipv4/ip_forwarding + after the /proc filesystem has been mounted. You need to say Y to + "IP firewalling" in order to be able to use IP masquerading (i.e. local computers can chat with an outside host, but that outside host is made to think that it is talking to the firewall box -- makes the local network completely invisible and avoids the need @@ -1089,7 +1130,7 @@ read Documentation/modules.txt for details. IP: always defragment -CONFIG_IP_ALWAYS_DEFRAG +CONFIG_IP_ALWAYS_DEFRAG This option means that all incoming fragments (= parts of IP packets that arose when some host between origin and destination decided that the IP packets were too large and cut them in pieces) will be @@ -1116,13 +1157,13 @@ used to connect to you. This is called "multihosting" or "virtual domains" and is explained in detail on the WWW at http://www.thesphere.com/~dlp/TwoServers/ (to browse the WWW, you - need to have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). Another scenario would be that - there are two logical networks living on your local ethernet and you - want to access them both with the same ethernet card. The - configuration of these alias addresses is done with a special name - syntax explained in Documentation/networking/alias.txt. If you want - this, say Y. Most people don't need it and say N. + need to have access to a machine on the Internet that has a program + like lynx or netscape). Another scenario would be that there are two + logical networks living on your local ethernet and you want to + access them both with the same ethernet card. The configuration of + these alias addresses is done with a special name syntax explained + in Documentation/networking/alias.txt. If you want this, say Y. Most + people don't need it and say N. IP: multicast routing CONFIG_IP_MROUTE @@ -1180,11 +1221,13 @@ over the net. "Path MTU Discovery" means that, instead of always sending very small chunks, we start out sending big ones and if we then discover that some host along the way likes its chunks smaller, - we adjust to a smaller size. This is good, so most people say - N here. However, some versions of DOS NCSA telnet (and other software) - are broken and can only connect to your Linux machine if you say Y - here. See Documentation/networking/ncsa-telnet for the location - of fixed NCSA telnet clients. If in doubt, say N. + we adjust to a smaller size. This is good, so most people say N + here, thereby not disabling it. However, some DOS software (versions + of DOS NCSA telnet and Trumpet Winsock in PPP mode) is broken and + won't be able to connect to your Linux machine correctly in all + cases (especially through a terminal server) unless you say Y + here. See Documentation/networking/ncsa-telnet for the location of + fixed NCSA telnet clients. If in doubt, say N. Path MTU Discovery (normally enabled) CONFIG_PATH_MTU_DISCOVERY @@ -1244,11 +1287,12 @@ http://playground.sun.com/pub/ipng/html/ipng-main.html; for specific information about IPv6 under Linux read the HOWTO at http://www.terra.net/ipv6/ and the file net/ipv6/README in the - kernel source. The IPv6 support is also available as a module ( = - code which can be inserted in and removed from the running kernel - whenever you want). The module will be called ipv6.o. If you want to - compile it as a module, say M here and read - Documentation/modules.txt. It's safe to say N for now. + kernel source. If you want to use IPv6, please upgrade to the newest + net-tools as given in Documentation/Changes. The IPv6 support is + also available as a module ( = code which can be inserted in and + removed from the running kernel whenever you want). The module will + be called ipv6.o. If you want to compile it as a module, say M here + and read Documentation/modules.txt. It's safe to say N for now. The IPX protocol CONFIG_IPX @@ -1311,27 +1355,28 @@ Appletalk DDP CONFIG_ATALK Appletalk is the way Apple computers speak to each other on a - network. EtherTalk is the name used for appletalk over ethernet and - Localtalk is appletalk over the apple serial links. If your linux - box is connected to such a network and you want to join the - conversation, say Y. You will need to use the netatalk package so - that your Linux box can act as a print and file server for macs as - well as access appletalk printers. Check out + network. If your linux box is connected to such a network and you + want to join the conversation, say Y. You will need to use the + netatalk package so that your Linux box can act as a print and file + server for macs as well as access appletalk printers. Check out http://artoo.hitchcock.org/~flowerpt/projects/linux-netatalk/ on the WWW for details (to browse the WWW, you need to have access to a - machine on the Internet that has one of the programs lynx, netscape - or Mosaic). The NET-2-HOWTO, available via ftp (user: anonymous) in + machine on the Internet that has a program like lynx or + netscape). EtherTalk is the name used for appletalk over ethernet + and the cheaper and slower LocalTalk is appletalk over a proprietary + apple network using serial links. Ethertalk is fully supported by + Linux, however the localtalk drivers are not yet ready to ship. The + kernel however supports localtalk and when such drivers become + available all you will need to do is download and install the + localtalk driver in order to join a Localtalk network. The + NET-2-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO contains valuable information as well. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called appletalk.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. I hear that the GNU boycott of Apple is over, so even politically - correct people are allowed to say Y here. At the time the kernel is - released the localtalk drivers are not yet ready to ship. The kernel - however supports localtalk and when such drivers become available - all you will need to do is download and install the localtalk - driver. + correct people are allowed to say Y here. IP-over-DDP support CONFIG_IPDDP @@ -1353,23 +1398,27 @@ COPS LocalTalk PC card support CONFIG_COPS - This allows you to use the COPS AppleTalk card to connect to LocalTalk - networks. You also need version 1.3.3 or later of the netatalk package. - This driver is experimental, which means that it may not work. - In particular the module support is not yet working for the 2.1.xx - kernels, so choose Y or N, but not M for now. - See the web site http://www.math.unm.edu/~bradford/ltpc.html for localtalk + This allows you to use COPS AppleTalk cards to connect to LocalTalk + networks. You also need version 1.3.3 or later of the netatalk + package. This driver is experimental, which means that it may not + work. In particular the module support is not yet working for the + 2.1.xx kernels, so choose Y or N, but not M for now. This driver + will only work if you choose "Appletalk DDP" networking support, + above. + Please read the file Documentation/networking/README.cops. See the + web site http://www.math.unm.edu/~bradford/ltpc.html for localtalk IP tools. Dayna firmware support CONFIG_COPS_DAYNA - Support COPS compatible cards with Dayna style firmware (Dayna DL2000/ - Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC III) + Support COPS compatible cards with Dayna style firmware (Dayna + DL2000/ Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC + III). Tangent firmware support CONFIG_COPS_TANGENT - Support COPS compatible cards with Tangent style firmware (Tangent ATB_II, - Novell NL-1000, Daystar Digital LT-200 + Support COPS compatible cards with Tangent style firmware (Tangent + ATB_II, Novell NL-1000, Daystar Digital LT-200. Amateur Radio AX.25 Level 2 CONFIG_AX25 @@ -1393,11 +1442,29 @@ source. More information about digital amateur radio in general is on the WWW at http://www.tapr.org/tapr/html/pkthome.html. (To browse the WWW, you need to have access to a machine on the Internet - that has one of the programs lynx, netscape or Mosaic). This driver - is also available as a module ( = code which can be inserted in and - removed from the running kernel whenever you want). The module will - be called ax25.o. If you want to compile it as a module, say M here - and read Documentation/modules.txt. + that has a program like lynx or netscape). This driver is also + available as a module ( = code which can be inserted in and removed + from the running kernel whenever you want). The module will be + called ax25.o. If you want to compile it as a module, say M here and + read Documentation/modules.txt. + +AX.25 DAMA Slave support +CONFIG_AX25_DAMA_SLAVE + DAMA is a mechanism to prevent collisions when doing AX.25 + networking. A DAMA server (called "master") accepts incoming traffic + from clients (called "slaves") and redistributes it to other + slaves. If you say Y here, your Linux box will act as a DAMA slave; + this is transparent in that you don't have to do any special DAMA + configuration. (Linux cannot yet act as a DAMA server.) If unsure, + say N. + +AX.25 DAMA Master support +CONFIG_AX25_DAMA_MASTER + DAMA is a mechanism to prevent collisions when doing AX.25 + networking. A DAMA server (called "master") accepts incoming traffic + from clients (called "slaves") and redistributes it to other + slaves. If you say Y here, your Linux box will act as a DAMA server. + If unsure, say N. Amateur Radio NET/ROM CONFIG_NETROM @@ -1409,11 +1476,11 @@ want to check out the file Documentation/networking/ax25.txt. More information about digital amateur radio in general is on the WWW at http://www.tapr.org/tapr/html/pkthome.html (To browse the WWW, you - need to have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). This driver is also available - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want). The module will be called - netrom.o. If you want to compile it as a module, say M here and read + need to have access to a machine on the Internet that has a program + like lynx or netscape). This driver is also available as a module ( + = code which can be inserted in and removed from the running kernel + whenever you want). The module will be called netrom.o. If you want + to compile it as a module, say M here and read Documentation/modules.txt. AX.25 over Ethernet @@ -1436,11 +1503,11 @@ out the file Documentation/networking/ax25.txt. More information about digital amateur radio in general is on the WWW at http://www.tapr.org/tapr/html/pkthome.html (To browse the WWW, you - need to have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). This driver is also available - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want). The module will be called - rose.o. If you want to compile it as a module, say M here and read + need to have access to a machine on the Internet that has a program + like lynx or netscape). This driver is also available as a module ( + = code which can be inserted in and removed from the running kernel + whenever you want). The module will be called rose.o. If you want to + compile it as a module, say M here and read Documentation/modules.txt. CCITT X.25 Packet Layer @@ -1462,25 +1529,30 @@ Documentation/networking/x25.txt and Documentation/networking/x25-iface.txt. One connects to an X.25 network either with a dedicated network card using the X.21 protocol - (not yet supported by Linux) or one can do X.25 over ethernet using - an ordinary ethernet card and either the 802.2 LLC protocol (say Y - to "802.2 LLC" below) or LAPB over ethernet (say Y to "LAPB Data - Link Driver" and "LAPB over Ethernet driver" below). If you want to - compile this driver as a module though ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called x25.o. If unsure, say N. + (not yet supported by Linux) or one can do X.25 over a standard + telephone line using an ordinary modem (say Y to "X.25 async driver" + below) or over ethernet using an ordinary ethernet card and either + the 802.2 LLC protocol (say Y to "802.2 LLC" below) or LAPB over + ethernet (say Y to "LAPB Data Link Driver" and "LAPB over Ethernet + driver" below). If you want to compile this driver as a module ( = + code which can be inserted in and removed from the running kernel + whenever you want), say M here and read + Documentation/modules.txt. The module will be called x25.o. If + unsure, say N. LAPB Data Link Driver (EXPERIMENTAL) CONFIG_LAPB - Link Access Procedure, Balanced (LAPB) is the data link layer part - of the X.25 protocol. It offers a reliable connection service to - exchange data frames with one other host, and it is used to - transport higher level protocols (mostly X.25 Packet Layer, but - others are possible as well). If you want to use LAPB connections - over ethernet, say Y here and to "LAPB over Ethernet driver" below. - Read Documentation/networking/lapb-module.txt for technical details. - If you want to compile this driver as a module though ( = code which + Link Access Procedure, Balanced (LAPB) is the data link layer + (i.e. the lower) part of the X.25 protocol. It offers a reliable + connection service to exchange data frames with one other host, and + it is used to transport higher level protocols (mostly X.25 Packet + Layer, the higher part of X.25, but others are possible as + well). Usually, LAPB is used with specialized X.21 network cards, but + Linux currently supports LAPB only over ethernet connections. If you + want to use LAPB connections over ethernet, say Y here and to "LAPB + over Ethernet driver" below. Read + Documentation/networking/lapb-module.txt for technical details. If + you want to compile this driver as a module though ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called lapb.o. If unsure, say N. @@ -1544,7 +1616,7 @@ and read Documentation/modules.txt and Documentation/scsi.txt. However, do not compile this as a module if your root filesystem (the one containing the directory /) is located - on a SCSI disk. + on a SCSI device. SCSI disk support CONFIG_BLK_DEV_SD @@ -1589,7 +1661,7 @@ required for some stuff which is newer than the SCSI-II standard: MultiSession CD support and some ioctls for reading Mode 2 Form 2 sectors. You'll probably want to say Y here, unless you have a - _real old_ CD-ROM drive. + _really old_ CD-ROM drive. SCSI generic support CONFIG_CHR_DEV_SG @@ -1676,12 +1748,13 @@ CONFIG_SCSI_AIC7XXX Information about this SCSI host adapter is contained in drivers/scsi/README.aic7xxx and in the SCSI-HOWTO, available via ftp - (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that - the AHA2920 SCSI host adapter is *not* supported by this driver; choose - "Future Domain 16xx SCSI support" instead. If you want to compile this - driver as module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read Documentation/ - modules.txt. The module will be called aic7xxx.o. + (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note + that the AHA2920 SCSI host adapter is *not* supported by this + driver; choose "Future Domain 16xx SCSI support" instead. If you + want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/ modules.txt. The module will be + called aic7xxx.o. Enable tagged command queueing CONFIG_AIC7XXX_TAGGED_QUEUEING @@ -1689,45 +1762,55 @@ driver. Some scsi devices do not properly support this feature. Tagged command queueing will improve performance. +Override driver defaults for commands per LUN +CONFIG_OVERRIDE_CMDS + This option allows you to set the maximum number of SCSI commands + queued per LUN (Logical Unit Number - some physical SCSI devices, + e.g. CD jukeboxes, act logically as several logical units). If you + say N here, the driver will attempt to set the commands per LUN + using its own reasonable heuristic. If you say Y, you can specify + your preference in the next question. If unsure, say N. + Maximum number of commands per LUN - CONFIG_AIC7XXX_CMDS_PER_LUN - This option allows you to set the maximum number of commands queued - per LUN. If tagged queueing is enabled, then you may want to try - increasing AIC7XXX_CMDS_PER_LUN to more than 2. By default, we limit - the SCBs per LUN to 2 with or without tagged queueing enabled. If - tagged queueing is disabled, the sequencer will keep the 2nd SCB in - the input queue until the first one completes - so it is OK to to have - more than 1 SCB queued. If tagged queueing is enabled, then the - sequencer will attempt to send the 2nd SCB to the device while the - first SCB is executing and the device is disconnected. For adapters - limited to 4 SCBs, you may want to actually decrease the commands per - LUN to 1, if you often have more than 2 devices active at the same - time. This will allocate 1 SCB for each device and ensure that there - will always be a free SCB for up to 4 devices active at the same time. - When SCB paging is enabled, set the commands per LUN to 8 or higher - (see SCB paging support below). Note that if AIC7XXX_CMDS_PER_LUN is - not defined and tagged queueing is enabled, the driver will attempt to - set the commands per LUN using its own heuristic based on the number - of available SCBs. +CONFIG_AIC7XXX_CMDS_PER_LUN + If tagged queueing is enabled, then you may want to try increasing + the number of SCSI commands per LUN to more than 2. By default, we + limit the commands per LUN to 2 with or without tagged queueing + enabled. If tagged queueing is disabled, the sequencer in the host + adapter will keep the 2nd command in the input queue until the first + one completes - so it is OK to have more than 1 command queued. If + tagged queueing is enabled, then the sequencer will attempt to send + the 2nd command block to the device while the first command block is + executing and the device is disconnected. For adapters limited to 4 + command blocks (SCB's), you may want to actually decrease the + commands per LUN to 1, if you often have more than 2 devices active + at the same time. This will ensure that there will always be a free + SCB for up to 4 devices active at the same time. When SCB paging is + enabled, set the commands per LUN to 8 or higher (see "SCB paging + support" below). If unsure, go with the default for now. Enable SCB paging CONFIG_AIC7XXX_PAGE_ENABLE This option enables SCB paging. This will increase performance when - tagged queueing is enabled. Note that you should increase the - AIC7XXX_CMDS_PER_LUN to 8 as most tagged queueing devices allow at - least this many. Note that EISA and VLB controllers do not support - SCB paging due to chip limitations; enabling it on these controllers - has no effect. + tagged queueing is enabled. Note that, if you say Y here, you + should increase the "Maximum number of commands per LUN" + (AIC7XXX_CMDS_PER_LUN) above to 8 as most tagged queueing devices + allow at least this many. Note that EISA and VLB controllers do not + support SCB paging due to chip limitations; enabling it on these + controllers has no effect. Collect statistics to report in /proc CONFIG_AIC7XXX_PROC_STATS This option enables collection of SCSI transfer statistics for the /proc filesystem. This does affect performance since it has to - maintain statistics. + maintain statistics. The statistics will appear under + /proc/scsi/aic7xxx. This will only work if you also enable the "proc + filesystem", below. Delay in seconds after SCSI bus reset CONFIG_AIC7XXX_RESET_DELAY - This option sets the delay in seconds after a SCSI bus reset. + This option sets the delay in seconds after a SCSI bus reset. If you + don't know what you are doing, go with the default. BusLogic SCSI support CONFIG_SCSI_BUSLOGIC @@ -1935,7 +2018,7 @@ Intel-based hardware. Under Linux/Alpha only normal IO is currently supported by the driver and so, this option has no effect. - The normal answer therefore is N. + The normal answer therefore is N. Try Y only if you have problems. not allow targets to disconnect CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT @@ -1945,6 +2028,25 @@ not allow targets to disconnect is not reasonable if there is more than 1 device on a scsi bus. The normal answer therefore is N. +detect and read serial NVRAMs +CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT + Enable support for reading the serial NVRAM data on Symbios and some + Symbios compatible cards, and Tekram DC390W/U/F cards. Useful for + systems with more than one Symbios compatible controller where at + least one has a serial NVRAM, or for a system with a mixture of + Symbios and Tekram cards. Enables setting the boot order of host + adaptors to something other than the default order or "reverse + probe" order. Also enables Symbios and Tekram cards to be + distinguished so that the option "assume boards are SYMBIOS + compatible" (CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT) below may be set + in a system with a mixture of Symbios and Tekram cards so that the + Symbios cards can make use of the full range of Symbios features, + differential, led pin, without causing problems for the Tekram + card(s). Also enables setting host and targets SCSI features as + defined in the user setup for each host using a serial NVRAM. Read + drivers/scsi/README.ncr53c8xx for more information. The default + answer is N, the normal answer should be Y. + enable tagged command queuing CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE This option allows you to enable tagged command queuing support at @@ -1967,25 +2069,6 @@ possible. The default value is 4. Minimum is 2, maximum is 12. The normal answer therefore is the default one. -detect and read serial NVRAM -CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT - Enable support for reading the serial NVRAM data on Symbios and - some Symbios compatible cards, and Tekram DC390W/U/F cards. Useful for - systems with more than one Symbios compatible controller where at least - one has a serial NVRAM, or for a system with a mixture of Symbios and - Tekram cards. Enables setting the boot order of host adaptors - to something other than the default order or "reverse probe" order. - Also enables Symbios and Tekram cards to be distinguished so - CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT may be set in a system with a - mixture of Symbios and Tekram cards so the Symbios cards can make use of - the full range of Symbios features, differential, led pin, without - causing problems for the Tekram card(s). - (added by Richard Waltham: dormouse@farsrobt.demon.co.uk) - Also enables setting host and targets SCSI features as defined in the - user setup for each host using a serial NVRAM (added by the maintainer). - The default answer is N, the normal answer should be Y. - Read drivers/scsi/README.ncr53c8xx for more information. - assume boards are SYMBIOS compatible CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT This option allows you to enable some features depending on GPIO @@ -2000,28 +2083,13 @@ (SDMS 4.0 + Promise SCSI ULTRA 875 rev 0x3 + ASUS SC200 810A rev 0x12). This option must be set to N if your system has at least one 53C8XX based scsi board with a vendor-specific BIOS (example: Tekram - DC-390/U/W/F). If unsure, say N. - However, if all your non Symbios compatible boards have NvRAM, setting - option CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT allows the driver to - distinguish Symbios compatible boards from other ones. - So, you can answer Y if all non Symbios compatible boards have NVRAM. - -assume boards are SYMBIOS compatible -CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT - This option allows you to enable some features depending on GPIO - wiring. These General Purpose Input/Output pins can be used for - vendor specific features or implementation of the standard SYMBIOS - features. Genuine SYMBIOS boards use GPIO0 in output for controller - LED and GPIO3 bit as a flag indicating singled-ended/differential - interface. - If all the boards of your system are genuine SYMBIOS boards or use - BIOS and drivers from SYMBIOS, you would want to enable this option, - obviously at your own risks. - The driver behaves correctly on my system with this option enabled. - (SDMS 4.0 + Promise SCSI ULTRA 875 rev 0x3 + ASUS SC200 810A rev - 0x12). This option must be set to N if your system has at least one - 53C8XX based scsi board with a vendor-specific BIOS (example: Tekram - DC-390/U/W/F). If unsure, say N. + DC-390/U/W/F). + However, if all your non Symbios compatible boards have NvRAM, + setting option "detect and read serial NVRAMs" + (CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT) above allows the driver to + distinguish Symbios compatible boards from other ones. So, you can + answer Y if all non Symbios compatible boards have NVRAM. + If unsure, say N. IBMMCA SCSI support CONFIG_SCSI_IBMMCA @@ -2031,13 +2099,17 @@ code which can be inserted in and removed from the running kernel whenever you want). The module will be called ibmmca.o. If you want to compile it as a module, say M here and read - Documentation/modules.txt. - Normally, all IBM MCA SCSI adapters are automatically detected. You - can completely override auto-detection by specifying - "ibmmcascsi=io1,io2,..." at the boot loader's command prompt or - "io_port=io1,io2,... scsi_id=id1,id2,..." as a parameter of insmod. - "io" and "id" are the I/O base address and the SCSI ID of each - adapter, respectively. + Documentation/modules.txt. + Normally, all IBM MCA SCSI adapters are automatically detected. If + that doesn't work right however, you can completely override + auto-detection by specifying "ibmmcascsi=io1,io2,..." at the boot + loader's command prompt or "io_port=io1,io2,... scsi_id=id1,id2,..." + as a parameter of insmod. "io" and "id" are the I/O base address + and the SCSI ID of each adapter, respectively. + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ibmmca.o. Always IN2000 SCSI support CONFIG_SCSI_IN2000 @@ -2189,17 +2261,27 @@ Tekram DC390W/U/F (T) SCSI support CONFIG_SCSI_DC390W - This driver supports the Tekram DC390W/U/F (T) PCI SCSI host adapters with - the NCR/Symbios 53c825/875 chips. If you have a DC390 (T) adaptor with the - Am53C974A chip use the DC390(T) driver. - + This driver supports the Tekram DC390W/U/F (T) PCI SCSI host + adapters with the NCR/Symbios 53c825/875 chips. Say Y here if you + have one of those. If however you have a DC390 (T) adaptor with the + Am53C974A chip, use the DC390(T) driver "Tekram DC390(T) (AMD + PCscsi) SCSI support", below. + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ???.o. + Tekram DC390(T) (AMD PCscsi) SCSI support CONFIG_SCSI_DC390T - This driver supports the Tekram DC390(T) PCI SCSI Hostadapter with + This driver supports the Tekram DC390(T) PCI SCSI host adapter with the Am53C974A chip, and perhaps other cards using the same chip. - This driver does _not_ support the DC390W/U/F adaptor with the - NCR/Symbios chips. + NCR/Symbios chips; use "Tekram DC390W/U/F (T) SCSI support" for that + one. + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called tmscsim.o. AM53/79C974 PCI SCSI support CONFIG_SCSI_AM53C974 @@ -2219,29 +2301,34 @@ driver and how to use it you should read the file drivers/scsi/README.ppa. You should also read the SCSI-HOWTO, which is available via anonymous ftp from sunsite.unc.edu in the directory - /pub/Linux/docs/HOWTO. This driver is also available as a module - which can be inserted in and removed from the running kernel - whenever you want. If you want to use any two of a parallel port ZIP - drive, a parallel printer or PLIP on the same parallel port, you - should compile the drivers as modules and only insert them as - needed. To compile this driver as a module, say M here and read - Documentation/modules.txt. The module will be called ppa.o. Note - that you can say N here if you have the SCSI version of the ZIP - drive: it will be supported automatically if you said Y to the - generic "SCSI disk support", above. + /pub/Linux/docs/HOWTO. If you use this driver, you will still be + able to use the parallel port for other tasks, such as a printer; it + is safe to compile both drivers into the kernel. This driver is also + available as a module which can be inserted in and removed from the + running kernel whenever you want. To compile this driver as a + module, say M here and read Documentation/modules.txt. The module + will be called ppa.o. Note that you can say N here if you have the + SCSI version of the ZIP drive: it will be supported automatically if + you said Y to the generic "SCSI disk support", above. EPP FIFO Checking CONFIG_SCSI_PPA_HAVE_PEDANTIC - Some chipsets are slower then their motherboard. We have to control - the state of the FIFO now and then. The values are 0 (don't check - FIFO), 1 (check FIFO every 4 bytes), 2 (check FIFO every other byte) - and 3 (check FIFO every time). If your EPP chipset is from the SMC - series, you are likely to have to set this value greater than 0. + EPP (Enhanced Parallel Port) is a standard for parallel ports which + allows them to act as expansion buses that can handle up to 64 + peripheral devices. Some parallel port chipsets are slower than + their motherboard, and so we have to control the state of the FIFO + every now and then to avoid data loss. The permitted values for + this option are 0 (don't check FIFO), 1 (check FIFO every 4 bytes), + 2 (check FIFO every other byte) and 3 (check FIFO every time). If + your EPP chipset is from the SMC series, you are likely to have to + set this value greater than 0. EPP Timing CONFIG_SCSI_PPA_EPP_TIME - This is the "reset time period", a delay time. Too low a value may - cause all sorts of mid-level SCSI problems. + This is the "reset time period", a delay time. The lower the value, + the faster the access to the ZIP drive; too low a value may + cause all sorts of mid-level SCSI problems however. If unsure, go + with the default. Network device support? CONFIG_NETDEVICES @@ -2253,33 +2340,23 @@ shell account or a BBS, even using term (term is a program which gives you almost full Internet connectivity if you have a regular dial up shell account on some Internet connected Unix computer. Read - the Term-HOWTO). You'll have to say Y if your computer contains a - network card that you want to use under linux (make sure you know - its name because you will be asked for it and read the - Ethernet-HOWTO; also, if you plan to use more than one network card - under linux, read the Multiple-Ethernet-mini-HOWTO, available from + http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html). You'll + have to say Y if your computer contains a network card that you want + to use under linux (make sure you know its name because you will be + asked for it and read the Ethernet-HOWTO; also, if you plan to use + more than one network card under linux, read the + Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini) or if you want to use SLIP (Serial Line Internet Protocol is the protocol used to send Internet traffic over telephone lines or nullmodem cables) or CSLIP - (compressed SLIP) or PPP (better and newer variant of SLIP) or PLIP - (Parallel Line Internet Protocol is mainly used to create a mini - network by connecting the parallel ports of two local machines) or - AX.25/KISS (protocol for sending internet traffic over radio links). - Make sure to read the NET-2-HOWTO. Eventually, you will have to - read Olaf Kirch's excellent book "Network Administrator's Guide", to - be found in sunsite.unc.edu:/pub/Linux/docs/LDP. If unsure, say Y. - -CONFIG_NET_ETHERNET - Ethernet is the most common protocol used on Local Area Networks - (LANs) in universities or companies. 10-base-2 and 10-base-T and - 100-base- are common types of ethernet. If your Linux - machine will be connected to an Ethernet and you have an ethernet - network card installed in your computer, say Y here and read the - Ethernet-HOWTO, available via ftp (user: anonymous) from - sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that the answer to this - question won't directly affect the kernel: saying N will just cause - this configure script to skip all the questions about Ethernet - network cards. If unsure, say N. + (compressed SLIP) or PPP (Point to Point Protocol, a better and + newer replacement for SLIP) or PLIP (Parallel Line Internet Protocol + is mainly used to create a mini network by connecting the parallel + ports of two local machines) or AX.25/KISS (protocol for sending + internet traffic over radio links). Make sure to read the + NET-2-HOWTO. Eventually, you will have to read Olaf Kirch's + excellent book "Network Administrator's Guide", to be found in + sunsite.unc.edu:/pub/Linux/docs/LDP. If unsure, say Y. Dummy net driver support CONFIG_DUMMY @@ -2296,8 +2373,8 @@ running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called dummy.o. If you want to use more than one dummy device at a time, you need to - compile it as a module. Instead of 'dummy', it will they will then - be called 'dummy0', 'dummy1' etc. + compile this driver as a module. Instead of 'dummy', the devices + will then be called 'dummy0', 'dummy1' etc. SLIP (serial line) support CONFIG_SLIP @@ -2318,11 +2395,12 @@ SLIP. Note that you don't need this option if you just want to run term (term is a program which gives you almost full Internet connectivity if you have a regular dial up shell account on some - Internet connected Unix computer. Read the Term-HOWTO). SLIP support - will enlarge your kernel by about 4kB. If unsure, say N. If you - want to compile this as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read Documentation/modules.txt as well as + Internet connected Unix computer. Read + http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html). SLIP + support will enlarge your kernel by about 4kB. If unsure, say N. If + you want to compile this as a module ( = code which can be inserted + in and removed from the running kernel whenever you want), say M + here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called slip.o. @@ -2394,20 +2472,41 @@ don't need "PPP support" if you just want to run term (term is a program which gives you almost full Internet connectivity if you have a regular dial up shell account on some Internet connected UNIX - computer. Read the Term-HOWTO). The PPP option enlarges your kernel - by about 16kB. This driver is also available as a module ( = code - which can be inserted in and removed from the running kernel - whenever you want). If you said Y to "Version information on all - symbols" above, then you cannot compile the PPP driver into the - kernel; you can then only compile it as a module. The module will be - called ppp.o. If you want to compile it as a module, say M here - and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. Note that, no matter what - you do, the BSD compression code (used to compress the IP packets - sent over the serial line; has to be supported at the other end as - well) can only be compiled as a module; it is called bsd_comp.o and - will show up in the directory modules once you have said "make - modules". If unsure, say N. + computer. Read + http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html). The PPP + option enlarges your kernel by about 16kB. This driver is also + available as a module ( = code which can be inserted in and removed + from the running kernel whenever you want). If you said Y to + "Version information on all symbols" above, then you cannot compile + the PPP driver into the kernel; you can then only compile it as a + module. The module will be called ppp.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt as well + as Documentation/networking/net-modules.txt. Note that, no matter + what you do, the BSD compression code (used to compress the IP + packets sent over the serial line; has to be supported at the other + end as well) will always be compiled as a module; it is called + bsd_comp.o and will show up in the directory modules once you have + said "make modules". If unsure, say N. + +Shortwave radio modem driver +CONFIG_HFMODEM + This experimental driver is used by a package (to be released) + that implements the shortwave radio protocols RTTY, Sitor (Amtor), + Pactor 1 and GTOR using a standard PC soundcard. If unsure, + say N. + +Shortwave radio modem driver support for SoundBlaster and compatible cards +CONFIG_HFMODEM_SBC + This option enables the hfmodem driver to use SoundBlaster and + compatible cards. It requires a 16bit capable card, i.e. + SB16 or better, or ESS1688 or newer. + +Shortwave radio modem driver support for WSS and Crystal cards +CONFIG_HFMODEM_WSS + This option enables the hfmodem driver to use WindowsSoundSystem + compatible cards. These cards feature a codec chip from either + Analog Devices (such as AD1848, AD1845) or Crystal + Semiconductors (such as CS4248, CS423x). STRIP (Metricom Starmode radio IP) CONFIG_STRIP @@ -2428,9 +2527,9 @@ the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called strip.o. -CONFIG_LAPBETHER LAPB over Ethernet driver - This is a driver for a pseudo device (usually called /dev/lapb0) +CONFIG_LAPBETHER + This is a driver for a pseudo device (typically called /dev/lapb0) which allows you to open an LAPB point-to-point connection to some other computer on your ethernet network. In order to do this, you need to say Y or M to the driver for your ethernet card as well as @@ -2440,6 +2539,18 @@ Documentation/modules.txt. The module will be called lapbether.o. If unsure, say N. +X.25 async driver +CONFIG_X25_ASY + This is a driver for sending and receiving X.25 frames over regular + asynchronous serial lines such as telephone lines equipped with + ordinary modems. Experts should note that this driver doesn't + currently comply with the asynchronous HDLS framing protocols in + CCITT recommendation X.25. If you want to compile this driver as a + module ( = code which can be inserted in and removed from the + running kernel whenever you want), say M here and read + Documentation/modules.txt. The module will be called x25_asy.o. If + unsure, say N. + Z8530 SCC driver for AX.25 CONFIG_SCC These cards are used to connect your Linux box to an amateur radio @@ -2459,11 +2570,11 @@ interface. The driver supports the ser12 and par96 designs. To configure the driver, use the sethdlc utility available in the standard ax25 utilities package. For information on the modems, see - http://www.baycom.de and drivers/net/README.baycom. If you want to - compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read Documentation/modules.txt. This is recommended. The module - will be called baycom.o. + http://www.baycom.de and Documentation/networking/baycom.txt. If you + want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is + recommended. The module will be called baycom.o. Soundcard modem driver for AX.25 CONFIG_SOUNDMODEM @@ -2474,9 +2585,9 @@ the standard ax25 utilities package. For information on how to key the transmitter, see http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html and - drivers/net/README.soundmodem. If you want to compile this driver as - a module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read + Documentation/networking/soundmodem.txt. If you want to compile this + driver as a module ( = code which can be inserted in and removed + from the running kernel whenever you want), say M here and read Documentation/modules.txt. This is recommended. The module will be called soundmodem.o. @@ -2508,24 +2619,24 @@ Soundcard modem support for 2400 baud AFSK modulation (7.3728MHz crystal) CONFIG_SOUNDMODEM_AFSK2400_7 This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with a 7.3728MHz crystal. - Note that the availability of this driver does _not_ imply that I - recommend building such links. It is only here since users especially - in eastern europe have asked me to do so. In fact this modulation scheme - has many disadvantages, mainly its incompatibility with many transceiver - designs and the fact that the TCM3105 (if used) is operated widely outside - its specifications. + compatible to TCM3105 modems (over-)clocked with a 7.3728MHz + crystal. Note that the availability of this driver does _not_ imply + that I recommend building such links. It is only here since users + especially in eastern Europe have asked me to do so. In fact this + modulation scheme has many disadvantages, mainly its incompatibility + with many transceiver designs and the fact that the TCM3105 (if + used) is operated widely outside its specifications. Soundcard modem support for 2400 baud AFSK modulation (8MHz crystal) CONFIG_SOUNDMODEM_AFSK2400_8 This option enables the soundmodem driver 2400 baud AFSK modem, compatible to TCM3105 modems (over-)clocked with an 8MHz crystal. Note that the availability of this driver does _not_ imply that I - recommend building such links. It is only here since users especially - in eastern europe have asked me to do so. In fact this modulation scheme - has many disadvantages, mainly its incompatibility with many transceiver - designs and the fact that the TCM3105 (if used) is operated widely outside - its specifications. + recommend building such links. It is only here since users + especially in eastern Europe have asked me to do so. In fact this + modulation scheme has many disadvantages, mainly its incompatibility + with many transceiver designs and the fact that the TCM3105 (if + used) is operated widely outside its specifications. Soundcard modem support for 4800 baud HAPN-1 modulation CONFIG_SOUNDMODEM_HAPN4800 @@ -2543,26 +2654,6 @@ can only use one protocol at a time, depending on what the other end can understand). -Shortwave radio modem driver -CONFIG_HFMODEM - This experimental driver is used by a package (to be released) - that implements the shortwave radio protocols RTTY, Sitor (Amtor), - Pactor 1 and GTOR using a standard PC soundcard. If unsure, - say N. - -Shortwave radio modem driver support for SoundBlaster and compatible cards -CONFIG_HFMODEM_SBC - This option enables the hfmodem driver to use SoundBlaster and - compatible cards. It requires a 16bit capable card, i.e. - SB16 or better, or ESS1688 or newer. - -Shortwave radio modem driver support for WSS and Crystal cards -CONFIG_HFMODEM_WSS - This option enables the hfmodem driver to use WindowsSoundSystem - compatible cards. These cards feature a codec chip from either - Analog Devices (such as AD1848, AD1845) or Crystal - Semiconductors (such as CS4248, CS423x). - Serial port KISS driver for AX.25 CONFIG_MKISS KISS is the protocol used to send IP traffic over AX.25 radio @@ -2598,24 +2689,7 @@ = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be - called plip.o. If you want to use both a parallel printer and PLIP, - there are two cases: 1) If the printer and the PLIP cable are to use - the same parallel port (presumably because you have just one), it is - best to compile both drivers as modules and load and unload them as - needed. 2) In order to use different parallel ports for the printer - and the PLIP cable, you can say Y to the printer driver and specify - the base address of the parallel port(s) to use for the printer(s) - with the "lp" kernel command line option. (Try "man bootparam" or - see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time. The lilo procedure - is also explained in the SCSI-HOWTO, available via ftp (user: - anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO.) The standard - base addresses as well as the syntax of the "lp" command line option - can be found in drivers/char/lp.c. You can then say Y to this PLIP - driver or, preferably, M in which case - Documentation/networking/net-modules.txt tells you how to specify - the port and IRQ to be used by PLIP at module load time. It's safe - to say N here. + called plip.o. EQL (serial line load balancing) support CONFIG_EQUALIZER @@ -2643,9 +2717,9 @@ relay network. For a general explanation of the protocol, check out http://frame-relay.indiana.edu/4000/4000index.html on the WWW. (To browse the WWW, you need to have access to a machine on the Internet - that has one of the programs lynx, netscape or Mosaic.) To use frame - relay, you need supporting hardware (FRAD) and certain programs from - the net-tools package as explained in + that has a program like lynx or netscape.) To use frame relay, you + need supporting hardware (FRAD) and certain programs from the + net-tools package as explained in Documentation/networking/framerelay.txt. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be @@ -2653,7 +2727,7 @@ and read Documentation/modules.txt. Max open DLCI -CONFIG_DLCI_COUNT +CONFIG_DLCI_COUNT This is the maximal number of logical point-to-point frame relay connections (the identifiers of which are called DCLIs) that the driver can handle. The default is probably fine. @@ -2695,8 +2769,8 @@ more information. WAN routing is always built as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called wanrouter.o. For general information - about modules read Documentation/modules.txt. + The module is called wanrouter.o. For general information about + modules read Documentation/modules.txt. WAN Drivers CONFIG_WAN_DRIVERS @@ -2767,11 +2841,19 @@ Ethernet (10 or 100Mbit) CONFIG_NET_ETHERNET - Ethernet is a widely used protocol on local area networks. If you - have a ethernet card in your computer and want to use it under - Linux, say Y here. Note that the answer to this question doesn't - directly affect the kernel: saying N will just cause this configure - script to skip all the questions about ethernet card drivers. + Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common + type of Local Area Networks (LANs) in universities or + companies. 10-base-2 or Thinnet (10 Mbps over coaxial cable, linking + computers in a chain), 10-base-T (10 Mbps over twisted pair + telephone cable, linking computers to a central hub) and + 100-base- (100 Mbps) are common types of ethernet. If your + Linux machine will be connected to an Ethernet and you have an + ethernet network card installed in your computer, say Y here and + read the Ethernet-HOWTO, available via ftp (user: anonymous) from + sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that the answer to this + question won't directly affect the kernel: saying N will just cause + this configure script to skip all the questions about Ethernet + network cards. If unsure, say N. Western Digital/SMC cards CONFIG_NET_VENDOR_SMC @@ -3112,13 +3194,14 @@ EtherExpressPro support CONFIG_EEXPRESS_PRO - If you have a network (ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is also available - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want). The module will be called - eepro.o. If you want to compile it as a module, say M here and read - Documentation/modules.txt as well as + If you have a network (ethernet) card of this type, say Y. Note + however that the EtherExpressPro 100 ethernet card has its own + separate driver. Please read the Ethernet-HOWTO, available via ftp + (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. This + driver is also available as a module ( = code which can be inserted + in and removed from the running kernel whenever you want). The + module will be called eepro.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. If you plan to use more than one network card under linux, read the Multiple-Ethernet-mini-HOWTO, available from @@ -3170,13 +3253,13 @@ which are commonly used to send internet traffic over amateur radio. More information about these cards is on the WWW at http://hydra.carleton.ca/info/pi2.html (To browse the WWW, you need - to have access to a machine on the Internet that has one of the - programs lynx, netscape or Mosaic). If you have one of these cards, - you can say Y here and should read the HAM-HOWTO, available via ftp - (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, - you should have said Y to "AX.25 support" above, because AX.25 is - the protocol used for digital traffic over radio links. If you want - to compile this as a module ( = code which can be inserted in and + to have access to a machine on the Internet that has a program like + lynx or netscape). If you have one of these cards, you can say Y + here and should read the HAM-HOWTO, available via ftp (user: + anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you + should have said Y to "AX.25 support" above, because AX.25 is the + protocol used for digital traffic over radio links. If you want to + compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called pi2.o. @@ -3196,18 +3279,26 @@ AT&T WaveLAN & DEC RoamAbout DS support CONFIG_WAVELAN - The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS) - is a Radio LAN (wireless ethernet-like) at 900 MHz and 2.4 GHz. - This driver support the ISA version of the Wavelan. A driver for - the pcmcia hardware is available in David Hinds's pcmcia package. - This driver is fairly stable and may be compiled as a module - (wavelan.o). It implements many nice feature and the Wireless - Extensions (you must get the Wireless tools from the net). - For documentation, refer to : - o the wavelan man page, wireless tools man pages - o wavelan.p.h and the source code - o Ethernet-HOWTO, Multiple-Ethernet-mini-HOWTO, Module-HOWTO - o More documentation to come when I will have the time :-) + The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS) is + a Radio LAN (wireless ethernet-like Local Area Network) using the + radio frequencies 900 MHz and 2.4 GHz. + This driver support the ISA version of the Wavelan card. A driver + for the pcmcia hardware is available in David Hinds's pcmcia + package. + If you want to use a card of this type under Linux, say Y and read + the Ethernet-HOWTO, available via ftp (user: anonymous) in + sunsite.unc.edu:/pub/Linux/docs/HOWTO. Some more specific + information is contained in drivers/net/README.wavelan. You will + also need the wireless tools package available from + ftp://ftp.inka.de/pub/comp/Linux/networking/NetTools/contrib/. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you + want). The module will be called wavelan.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt as + well as Documentation/networking/net-modules.txt. If you plan to use + more than one network card under linux, read the + Multiple-Ethernet-mini-HOWTO, available from + sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. HP PCLAN+ (27247B and 27252A) support CONFIG_HPLAN_PLUS @@ -3287,6 +3378,15 @@ Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. +AMD PCnet32 (VLB and PCI) support +CONFIG_PCNET32 + if you have a PCnet32 or PCnetPCI based network (ethernet) card, say + Y here and read the Ethernet-HOWTO, available via ftp (user: + anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to + use more than one network card under linux, read the + Multiple-Ethernet-mini-HOWTO, available from + sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Ansel Communications EISA 3200 support CONFIG_AC3200 If you have a network (ethernet) card of this type, say Y and read @@ -3380,6 +3480,20 @@ Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. +EtherExpressPro/100 support +CONFIG_EEXPRESS_PRO100 + If you have an Intel EtherExpressPro 100 PCI network (ethernet) + card, say Y and read the Ethernet-HOWTO, available via ftp (user: + anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is + also available as a module ( = code which can be inserted in and + removed from the running kernel whenever you want). The module will + be called eepro100.o. If you want to compile it as a module, say M + here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. If you plan to use more + than one network card under linux, read the + Multiple-Ethernet-mini-HOWTO, available from + sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + ICL EtherTeam 16i/32 support CONFIG_ETH16I If you have a network (ethernet) card of this type, say Y and read @@ -3397,10 +3511,11 @@ TI ThunderLAN support (EXPERIMENTAL) CONFIG_TLAN If you have a TLAN based network card which is supported by this - driver, say Y and read the Ethernet-HOWTO. Devices currently supported - are the Compaq Netelligent 10, Netelligent 10/100, and Internal - NetFlex 3. This driver is also available as a module. Please email - feedback to james.banks@caldera.com. + driver, say Y and read the Ethernet-HOWTO. Devices currently + supported are the Compaq Netelligent 10, Netelligent 10/100, and + Internal NetFlex 3. This driver is also available as a module. The + module will be called tlan.o. Please email feedback to + james.banks@caldera.com. Zenith Z-Note support CONFIG_ZNET @@ -3426,9 +3541,7 @@ asked for your specific device in the following questions. If you plan to use more than one network device under linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you intend to use an - adapter attaching to the parallel port as well as a parallel - printer, you should compile both drivers as modules (if possible). + sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. AT-LAN-TEC/RealTek pocket adapter support CONFIG_ATP @@ -3447,30 +3560,30 @@ This is a network (ethernet) device which attaches to your parallel port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO, available via ftp (user: anonymous) from - sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. If - you want to compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read Documentation/modules.txt. The module will be called - de600.o. If you intend to use this pocket adapter as well as a - parallel printer, you should compile both drivers as modules. If you - plan to use more than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. It is + possible to have several devices share a single parallel port and it + is safe to compile the corresponding drivers into the kernel. If you + want to compile this driver as a module however ( = code which can + be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called de600.o. If you plan to use more than one network + card under linux, read the Multiple-Ethernet-mini-HOWTO, available + from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. D-Link DE620 pocket adapter support CONFIG_DE620 This is a network (ethernet) device which attaches to your parallel port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO, available via ftp (user: anonymous) from - sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. If - you want to compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read Documentation/modules.txt. The module will be called - de620.o. If you intend to use this pocket adapter as well as a - parallel printer, you should compile both drivers as modules. If you - plan to use more than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + sunsite.unc.edu:/pub/Linux/docs/HOWTO if you want to use this. It is + possible to have several devices share a single parallel port and it + is safe to compile the corresponding drivers into the kernel. If you + want to compile this driver as a module however ( = code which can + be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called de620.o. If you plan to use more than one network + card under linux, read the Multiple-Ethernet-mini-HOWTO, available + from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. Token Ring driver support CONFIG_TR @@ -3680,9 +3793,13 @@ other models). Say Y if you have one of these, and read the file Documentation/cdrom/bpcd. If you say Y here, you should also say Y to "ISO9660 cdrom filesystem support" below, because that's the - filesystem used on CDROMs. If you have several different devices - that will share a common parallel port, say M and build them as - modules. This module will be called bpcd.o. + filesystem used on CDROMs. It is possible for several devices to + share a parallel port and it is safe to compile the corresponding + drivers all into the kernel. This driver is also available as a + module ( = code which can be inserted in and removed from the + running kernel whenever you want). The module will be called + bpcd.o. If you want to compile it as a module, say M here and read + Documentation/modules.txt. Philips/LMS CM206 CDROM support CONFIG_CM206 @@ -3744,10 +3861,12 @@ Preload dcache CONFIG_DCACHE_PRELOAD Preloading will create dcache entries when a directory is scanned - (e.g. with ls) the *first* time. This should speed up successive - inode lookups, but also can consume large amounts of memory. + (e.g. with ls) for the *first* time. This should speed up successive + lookups of information about files in that directory, but can also + consume large amounts of memory. Please report speedups (or slowdowns due to the memory usage if they occur) to schoebel@informatik.uni-stuttgart.de . + If unsure, say N. Quota support CONFIG_QUOTA @@ -3777,118 +3896,136 @@ Filename translation support CONFIG_TRANS_NAMES - Normally used only when you want diskless clients to mount the root - filesystem of the server. If unsure, or if you don't have clients, select N. - When selected, filenames, directory names etc become context-sensitive. - If you have a file named "/etc/config#host=banana#", it will appear - (by default) as hardlinked to "/etc/config" on host "banana", while on host - "mango" another file "/etc/config#host=mango#" will appear as been - hardlinked to "/etc/config". The default behaviour can be changed - by setting the _first_ environment variable NAMETRANS to a colon-separated - list of suffixes which are tried in the specified order. For example, - in 'env - NAMETRANS=#host=mango#:#ktype=diskless# "`env`" command ...' the - command will see the same files as if it had been executed on host "mango" - with a diskless kernel. Using NAMETRANS supersedes _all_ default - translations. Thus translations can be generally switched off by an - empty list, e.g. 'env - NAMETRANS= "`env`" command ...'. - Note that some system utililies like tar, dump, restore should - be used with translation switched off, in order to avoid doubled - space in archive files and when extracting from them. Also, make sure - that nfsd, mountd (and similar ones like samba daemons) run without - translation, in order to avoid doubled (or even wrong) translation - at the server and at the client. You can automatically force the creation - of context-dependent filenames if there exists a template filename like - "/etc/mtab#host=CREATE#". As soon as a process running on "mango" tries - to create a file "/etc/mtab", the version "/etc/mtab#host=mango#" is - created instead (which appears in turn as hardlinked to "/etc/mtab"). - Note that if you want to make "/etc/fstab" context-dependend, you should - execute "touch /etc/mtab#host=CREATE#" and - "touch /etc/mtab.tmp#host=CREATE#", because mount, umount and others - running on different hosts would otherwise try to create one shared - /etc/mtab which would result in a clash. Also one should execute - "touch /etc/nologin#host=CREATE#" to prevent global side effects from - shutdown resp. runlevel. + This is a useful feature if you have a pool of diskless Linux + clients which mount their root filesystems from a central + server. Depending on their hostnames, the clients can then see + different versions of certain files, which keeps maintenance at a + minimum when used for configuration files. The kernel running on the + clients should have this option enabled. If you don't administer a + pool of Linux clients, say N here, otherwise read on: + When you say Y here, filenames, directory names etc become + context-sensitive. If you have a file named + "/etc/config#host=banana#", it will appear (by default) as + hardlinked to "/etc/config" on host "banana", while on host "mango" + another file "/etc/config#host=mango#" will appear as having been + hardlinked to "/etc/config". + This default behaviour can be changed by setting the _first_ + environment variable NAMETRANS to a colon-separated list of suffixes + which are tried in the specified order. For example, in 'env - + NAMETRANS=#host=mango#:#ktype=diskless# "`env`" command ...' the + command will see the same files as if it had been executed on host + "mango" with a diskless kernel. + Using NAMETRANS supersedes _all_ default translations. Thus + translations can be completely switched off with an empty list, + e.g. 'env - NAMETRANS= "`env`" command ...'. Note that some system + utilities like tar, dump, restore should be used with translation + switched off, in order to avoid doubled space in archive files and + when extracting from them. Also, make sure that nfsd, mountd (and + similar ones like samba daemons) run without translation, in order + to avoid doubled (or even wrong) translation at the server and at + the client. + You can automatically force the creation of context-dependent + filenames if there exists a template filename like + "/etc/mtab#host=CREATE#". As soon as a process running on "mango" + tries to create a file "/etc/mtab", the version + "/etc/mtab#host=mango#" is created instead (which appears in turn as + hardlinked to "/etc/mtab"). Note that if you want to make + "/etc/fstab" context-dependent, you should execute "touch + /etc/mtab#host=CREATE#" and "touch /etc/mtab.tmp#host=CREATE#", + because mount, umount and others running on different hosts would + otherwise try to create one shared /etc/mtab which would result in a + clash. Also one should execute "touch /etc/nologin#host=CREATE#" to + prevent global side effects from shutdown resp. runlevel. + Please read Documentation/transname.txt if you intend to say Y here. Restrict translation to gid CONFIG_TRANS_RESTRICT - When selected, default translations are carried out only if the parent - directory of the context-sensitive file belongs to a specific group id - (gid). Trying to translate names everywhere will decrease performance of - file openings. Normally translations are used only in system configuration - files but not in ordinary user filespace. So you should change the gid of - directories containing context-dependent files to some special group like - "adm" (group id 4) and enable this option. As a result, users will not - notice any performance degradation resulting from filename translation. + If you say Y here, default filename translations are carried out + only if the parent directory of the context-sensitive file belongs + to a specific group id (gid). Trying to translate names everywhere + will decrease performance of file openings. Normally translations + are used only in system configuration files but not in ordinary user + filespace. So you should change the gid of directories containing + context-dependent files to some special group like "adm" (group id + 4) and enable this option. As a result, users will not notice any + performance degradation resulting from filename translation. Note that translations resulting from the first environment variable - "NAMETRANS=..." are always carried out regardless of the gid of directories. - Beware, before turning on this option make sure all directories containing - context-dependent files belong to the special group, or system - initialization may fail. In unsure, select N. + "NAMETRANS=..." are always carried out regardless of the gid of + directories. + Beware: before turning on this option make sure that all directories + containing context-dependent files belong to the special group, or + system initialization may fail. If unsure, select N. Group id (gid) for translation restriction CONFIG_TRANS_GID Default name translations will be carried out only inside directories - belonging to the group id (gid) you can specify here. + belonging to the group id (gid) that you specify here. Default is 4 (group "adm"). Nodename (hostname) translation CONFIG_TR_NODENAME - Enables translation of name suffixes like in "/etc/config#host=banana#". - The syntax is #host=#. The hostname can be queried - with the command "uname -n". Normally this option is used heavily when + Enables translation of name suffixes like in + "/etc/config#host=banana#". The syntax is + #host=#. The hostname can be queried with the + command "uname -n". Normally this option is used heavily when translation is enabled. If unsure, say Y. Kernelname translation CONFIG_TR_KERNNAME - Enables translation of name suffixes like in "/etc/config#kname=default#". - The string is hard compiled into the kernel by the following option. - Useful if your kernel does not know the hostname at boot time, and there - is no way to tell the hostname by lilo or bootp. Please avoid using this - option and prefer CONFIG_TR_NODENAME wherever possible. When mounting - the root over nfs, the own hostname must be known at boot time anyway; - this option is just for special use. - Note that the default translations are tried in the order as occuring - in the configuration, that is 1) host 2) kname 3) ktype 4) machine - 5) system. If unsure, say Y. + Enables translation of name suffixes like in + "/etc/config#kname=default#". The string is hard compiled into the + kernel by the following option. Useful if your kernel does not know + the hostname at boot time, and there is no way to tell the hostname + by lilo or bootp. Please avoid using this option and prefer + "Nodename (hostname) translation" (CONFIG_TR_NODENAME) wherever + possible. When mounting the root over nfs, the own hostname must be + known at boot time anyway; this option is just for special use. + Note that the default translations are tried in the order as + occurring in the configuration, that is 1) host 2) kname 3) ktype 4) + machine 5) system. If unsure, say Y. String for kernelname translation CONFIG_KERNNAME Enter the string you want to compile into the kernel. The string - will be used as context in context-depenant file like - "/etc/config#kname=#". + will be used as context in context-dependent files like + "/etc/config#kname=#". Kerneltype translation CONFIG_TR_KERNTYPE - Enables translation of name suffixes like in "/etc/config#ktype=default#". - The syntax is #ktype=#. The string is hard compiled - in the kernel by the following option. Use if you want to create - different kernels with different behaviour. For example, use the string - "default" on your server, and use "diskless" on all your diskless clients - (and perhaps "dataless" on dataless clients). This way you can avoid - dozens of "config#host=# with same contents and you have no - effort when new machines are added. If unsure, say Y. + Enables translation of name suffixes like in + "/etc/config#ktype=default#". The syntax is + #ktype=#. The string is hard compiled in the + kernel by the following option. Use if you want to create different + kernels with different behaviour. For example, use the string + "default" on your server, and use "diskless" on all your diskless + clients (and perhaps "dataless" on dataless clients). This way you + can avoid dozens of "config#host=# with same contents and + you have no effort when new machines are added. If unsure, say Y. String for kerneltype translation CONFIG_KERNTYPE Enter the string you want to compile into the kernel. The string - will be used as context in context-depenant file like - "/etc/config#ktype=default#". If your kernel is to be used on a server, - you probably can use "default" here. If your kernel is intended for - a diskless client, you probably should enter "diskless" here. + will be used as context in context-dependent files like + "/etc/config#ktype=default#". If your kernel is to be used on a + server, you probably can use "default" here. If your kernel is + intended for a diskless client, you probably should enter "diskless" + here. Machine type translation CONFIG_TR_MACHINE - Enables translation of name suffixes like in "/etc/config#machine=i486#". - The syntax is #machine=#. The machine types can be queried - with the command "uname -m". Normally used only on multi-architecture + Enables translation of name suffixes like in + "/etc/config#machine=i486#". The syntax is + #machine=#. The machine types can be queried with the + command "uname -m". Normally used only on multi-architecture installations. If unsure, say Y. System name translation CONFIG_TR_SYSNAME - Enables translation of name suffixes like in "/etc/config#system=Linux#". - The syntax is #system=#. The system name can be queried - with the command "uname -s". Currently only supportet by Linux, but - hopefully other operating systems will pick up the idea of context-dependent + Enables translation of name suffixes like in + "/etc/config#system=Linux#". The syntax is + #system=#. The system name can be queried with the + command "uname -s". Currently only supported by Linux, but hopefully + other operating systems will pick up the idea of context-dependent translations. If unsure, say Y. Minix fs support @@ -4065,7 +4202,24 @@ If you want your Linux box to mount its whole root filesystem from some other computer over the net via NFS (presumably because your box doesn't have a harddisk), say Y. Read Documentation/nfsroot.txt - for details. Most people say N here. + for details. Most people say N here. + +NFS server support +CONFIG_NFSD + If you want your Linux box to act as a NFS *server*, so that other + computers on your local network which support NFS can access files + on your box transparently, you have two options: you can use the + self-contained user space program nfsd, in which case you should say + N here, or you can say Y and use this new experimental kernel based + NFS server. The advantage of the kernel based solution is that it is + faster; it might not be completely stable yet, though. You will need + the support software from the linux-nfs package available at + ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/. + The nfs server is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you + want). The module is called nfsd.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. If unsure, + say N. BOOTP support CONFIG_RNFS_BOOTP @@ -4086,8 +4240,8 @@ some other computer over the net via NFS and you want the IP address of your computer to be discovered automatically at boot time using the RARP protocol (an older protocol which is being obsoleted by - BOOTP), say Y here. Note that in case you want to use RARP, a RARP - server must be operating on your network. Read + BOOTP and DHCP), say Y here. Note that in case you want to use RARP, + a RARP server must be operating on your network. Read Documentation/nfsroot.txt for details. ISO9660 cdrom filesystem support @@ -4152,10 +4306,14 @@ on demand. This implementation is partially kernel-based to reduce overhead in the already-mounted case; this is unlike the BSD automounter (amd), which is only in user space. To use the - automounter you also need the user-space tools from - ftp.kernel.org:/pub/linux/daemons/autofs. If you are not a part of - a fairly large, distributed network, you probably do not need an - automounter, and can say N here. + automounter you need the user-space tools from + ftp.kernel.org:/pub/linux/daemons/autofs; you also want to say Y to + "NFS filesystem support", above. If you want to compile this as a + module ( = code which can be inserted in and removed from the + running kernel whenever you want), say M here and read + Documentation/modules.txt. The module will be called autofs.o. + If you are not a part of a fairly large, distributed network, you + probably do not need an automounter, and can say N here. BSD UFS filesystem support (read only) CONFIG_UFS_FS @@ -4204,7 +4362,9 @@ (WfW), Windows 95, Windows NT and Lan Manager use to share files and printers over local networks. Saying Y here allows you to mount their filesystems (often called "shares" in this context) and access - them just like any other unix directory. For details, read + them just like any other unix directory. Currently, this works only + if the Windows machines use TCP/IP as the underlying transport + protocol, and not Netbeui. For details, read Documentation/filesystems/smbfs.txt. Note: if you just want your box to act as an SMB *server* and make files and printing services available to Windows clients (which need to have a TCP/IP stack), @@ -4213,12 +4373,12 @@ sunsite.unc.edu:/pub/Linux/system/Network/samba) for that. General information about how to connect Linux, Windows machines and Macs is on the WWW at http://eats.com/linux_mac_win.html (to browse the WWW, - you need to have access to a machine on the Internet that has one of - the programs lynx, netscape or Mosaic). If you want to compile the - SMB support as a module ( = code which can be inserted in and - removed from the running kernel whenever you want), say M here and - read Documentation/modules.txt. The module will be called - smbfs.o. Most people say N, however. + you need to have access to a machine on the Internet that has a + program like lynx or netscape). If you want to compile the SMB + support as a module ( = code which can be inserted in and removed + from the running kernel whenever you want), say M here and read + Documentation/modules.txt. The module will be called smbfs.o. Most + people say N, however. SMB Win95 bug work-around CONFIG_SMB_WIN95 @@ -4276,14 +4436,15 @@ CONFIG_VT This includes support for a terminal device using display and keyboard devices. Only people using embedded systems want to say N - here. Most say Y here. + here; most everybody says Y. Console on virtual terminal CONFIG_VT_CONSOLE If you enable this option, all kernel messages will be sent to the device /dev/tty which corresponds to the virtual terminal you have - visible on your display. You should say Y here if you have no other - console device. + visible on your display. You should say N here only if you have some + other console device, in which case you probably want to say Y to + "Console on serial port", below. If unsure, say N. Standard/generic serial support CONFIG_SERIAL @@ -4307,22 +4468,37 @@ Console on serial port CONFIG_SERIAL_CONSOLE If you enable this option, all kernel messages will be sent to the - device /dev/ttyS1 which corresponds to a serial port; this could be - useful if you attached a terminal or printer to that port. You can - use this in combination with console on virtual terminal, in which - case you get the output on both serial and display. Most people say - N here so that they can use the serial port for modem, mouse or some - other device. + device /dev/ttyS0 which corresponds to a serial port; this could be + useful if you attached a terminal or printer to that port. (You can + change the number of the serial port used from 0 to something else + by setting the variable CONFIG_SERIAL_CONSOLE_PORT.) You can use + this option in combination with the option "Console on virtual + terminal" above, in which case you get the output on both the serial + port and on your display. Most people say N here so that they can + use the serial port for modem, mouse or some other device. + +Comtrol Rocketport support +CONFIG_ROCKETPORT + This is a driver for the Comtrol Rocketport cards which provide + multiple serial ports. You would need something like this to + connect more than two modems to your linux box, for instance in + order to become a BBS.If you want to compile this driver as a + module, say M here and read Documentation/modules.txt. The module + will be called rocket.o. -Digi Intl. epca support +Digiboard Intelligent async support CONFIG_DIGIEPCA - This is a driver for Digi Internationals Xx, Xeve, and Xem - series of cards. This driver supports the original PC (ISA) boards as - well as PCI, and EISA. If you have a card like this, say Y here and read - the file Documentation/digiepca.txt. NOTE: This driver is seperate from - the driver written and copyrighted by Troy De Jongh. Because they both - attempt (In some cases) to access the same hardware only one of these - drivers (CONFIG_DIGIEPCA or CONFIG_DIGI) should be selected. + This is a driver for Digi International's Xx, Xeve, and Xem series + of cards which provide multiple serial ports. You would need + something like this to connect more than two modems to your linux + box, for instance in order to become a BBS. This driver supports the + original PC (ISA) boards as well as PCI, and EISA. If you have a + card like this, say Y here and read the file + Documentation/digiepca.txt. NOTE: There is another, separate driver + for the Digiboard PC boards: "Digiboard PC/Xx Support" below. You + should (and can) only select one of the two drivers. If you want to + compile this driver as a module, say M here and read + Documentation/modules.txt. The module will be called epca.o. Digiboard PC/Xx Support CONFIG_DIGI @@ -4387,7 +4563,7 @@ CONFIG_ESPSERIAL This is a driver which supports Hayes ESP serial ports. It uses DMA to transfer data to and from the host. Make sure to read - drivers/char/README.esp. To compile this driver as a module ( = code + Documentation/hayes-esp.txt. To compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called esp.o. @@ -4401,35 +4577,38 @@ Hayes ESP serial port receive trigger level CONFIG_ESPSERIAL_RX_TRIGGER - This is the trigger level (in bytes) of the receive FIFO. Larger values - may result in fewer interrupts; however, a value too high could result in - data loss. Valid values are 1 through 1023. + This is the trigger level (in bytes) of the receive FIFO. Larger + values may result in fewer interrupts; however, a value too high + could result in data loss. Valid values are 1 through 1023. Hayes ESP serial port transmit trigger level CONFIG_ESPSERIAL_TX_TRIGGER - This is the trigger level (in bytes) of the transmit FIFO. Larger values - may result in fewer interrupts; however, a value too high could result in - degraded trasmit performance. Valid values are 1 through 1023. + This is the trigger level (in bytes) of the transmit FIFO. Larger + values may result in fewer interrupts; however, a value too high + could result in degraded transmit performance. Valid values are 1 + through 1023. Hayes ESP serial port flow off level CONFIG_ESPSERIAL_FLOW_OFF - This is the level (in bytes) at which the ESP port will flow off the remote - transmitter. Valid values are 1 through 1023. This value should be greater - than the receive trigger level and the flow on level. + This is the level (in bytes) at which the ESP port will "flow off" + the remote transmitter (i.e. tell him to stop stop sending more + bytes). Valid values are 1 through 1023. This value should be + greater than the receive trigger level and the flow on level. Hayes ESP serial port flow on level CONFIG_ESPSERIAL_FLOW_ON - This is the level (in bytes) at which the ESP port will flow on the remote - transmitter after having flowed it off. Valid values are 1 through 1023. - This value should be less than the flow off level, but greater than the - receive trigger level. + This is the level (in bytes) at which the ESP port will "flow on" + the remote transmitter (i.e. tell him to resume sending bytes) after + having flowed it off. Valid values are 1 through 1023. This value + should be less than the flow off level, but greater than the receive + trigger level. Hayes ESP serial port receiver timeout CONFIG_ESPSERIAL_RX_TMOUT - This is the amount of time that the ESP port will wait after receiving the - final character before signalling an interrupt. Valid values are 0 through - 255. A value too high will increase latency, and a value too low will cause - unnecessary interrupts. + This is the amount of time that the ESP port will wait after + receiving the final character before signaling an interrupt. Valid + values are 0 through 255. A value too high will increase latency, + and a value too low will cause unnecessary interrupts. Parallel printer support CONFIG_PRINTER @@ -4437,15 +4616,27 @@ box (as opposed to using a serial printer; if the connector at the printer has 9 or 25 holes ["female"], then it's serial), say Y. Also read the Printing-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you want to compile this - as a module ( = code which can be inserted in and removed from the - running kernel whenever you want), say M here and read - Documentation/modules.txt. + sunsite.unc.edu:/pub/Linux/docs/HOWTO. It is possible to share one + parallel port among several devices (e.g. printer and ZIP drive) and + it is safe to compile the corresponding drivers into the kernel. If + you want to compile this driver as a module however ( = code which + can be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called lp.o. If you have several parallel ports, you + should specify the base address for the port to use by the printer + with the "lp" kernel command line option. (Try "man bootparam" or + see the documentation of your boot loader (lilo or loadlin) about + how to pass options to the kernel at boot time. The lilo procedure + is also explained in the SCSI-HOWTO, available via ftp (user: + anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO.) The standard + base addresses as well as the syntax of the "lp" command line option + can be found in drivers/char/lp.c. If you have more than 3 printers, + you need to increase the LP_NO variable in lp.c. CONFIG_PRINTER_READBACK - If your printer conforms to IEEE 1284, it may be able to provide a status - indication when you read from it (for example, with `cat /dev/lp1'). To - use this feature, say Y here. + If your printer conforms to IEEE 1284, it may be able to provide a + status indication when you read from it (for example, with `cat + /dev/lp1'). To use this feature, say Y here. Mouse Support (not serial mice) CONFIG_MOUSE @@ -4489,12 +4680,14 @@ explained in detail in the Busmouse-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. When using a PS/2 mouse, you can get problems if you want to use the mouse both - on the Linux console and under X. The mconv utility, available in - sunsite.unc.edu:/pub/Linux/system/Misc, solves this problem. If you - want to compile this mouse driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called psaux.o. If you are unsure, say N and read the HOWTO + on the Linux console and under X. Using the "-R" option of the Linux + mouse managing program gpm (available from + sunsite.unc.edu:/pub/Linux/system/Daemons) solves this problem, or + you can get the "mconv" utility also from sunsite. + If you want to compile this mouse driver as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called psaux.o. If you are unsure, say N and read the HOWTO nevertheless: it will tell you what you have. C&T 82C710 mouse port support (as on TI Travelmate) @@ -4506,9 +4699,13 @@ PC110 digitizer pad support CONFIG_PC110_PAD - This drives the digitizer pad on the IBM PC110 palmtop (see - http://toy.cabi.net). It can turn the digitizer pad into a - mouse emulation with tap gestures or into an absolute pad. + This drives the digitizer pad on the IBM PC110 palmtop (see + http://toy.cabi.net). It can turn the digitizer pad into a PS/2 + mouse emulation with tap gestures or into an absolute pad. If you + want to compile this as a module ( = code which can be inserted in + and removed from the running kernel whenever you want), say M here + and read Documentation/modules.txt. The module will be called + pc110pad.o. Microsoft busmouse support CONFIG_MS_BUSMOUSE @@ -4761,13 +4958,34 @@ CONFIG_NVRAM If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), - you get access to the non-volatile memory in the real time clock - (RTC). This is conventionally called "CMOS RAM" on PCs and "NVRAM" - on Ataris. /dev/nvram may be used to view settings there, or to - change them (with some utility). It could also be used to frequently - save a few bits of very important data, that may not be lost over - power-off and for which writing to disk is too insecure. On Atari - machines, /dev/nvram is always configured and needs not be selected. + you get access to the 50 bytes of non-volatile memory in the real + time clock (RTC), which is contained in every PC and most + Ataris. This memory is conventionally called "CMOS RAM" on PCs and + "NVRAM" on Ataris. /dev/nvram may be used to view settings there, or + to change them (with some utility). It could also be used to + frequently save a few bits of very important data that may not be + lost over power-off and for which writing to disk is too + insecure. On Atari machines, /dev/nvram is always configured and + does not need to be selected. This driver is also available as a + module ( = code which can be inserted in and removed from the + running kernel whenever you want). The module will be called + nvram.o. If you want to compile it as a module, say M here and read + Documentation/modules.txt. + +PC joystick support +CONFIG_JOYSTICK + If you have a joystick, you can say Y here. If you then create a + character special file under /dev with major number 15 and minor + number 0 or 1 (for the two joystick ports) using mknod ("man + mknod"), you can read the status of the buttons and the x and y + coordinates from that file. More information, an example program and + a calibration program are contained in the joystick package which is + available via ftp (user: anonymous) in + sunsite.unc.edu/pub/Linux/kernel/patches/console/. This driver is + also available as a module ( = code which can be inserted in and + removed from the running kernel whenever you want). The module will + be called joystick.o. If you want to compile it as a module, say M + here and read Documentation/modules.txt. ARC console time CONFIG_RTC_ARC @@ -4902,18 +5120,14 @@ Support for Crystal CS4232 based (PnP) cards CONFIG_CS4232 - Say Y here if you have a card based on the Crystal CS4232 chip set. + Say Y here if you have a card based on the Crystal CS4232 chip set, + which use the Plug and Play protocol. Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers CONFIG_MAUI Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez sound card. -Support for Crystal CS4232 based (PnP) cards -CONFIG_CS4232 - Use this option to enable experimental support for cards that use - the Plug and Play protocol. - /dev/dsp and /dev/audio support CONFIG_AUDIO Answering N disables /dev/dsp and /dev/audio, the A/D and D/A @@ -4960,36 +5174,35 @@ Gallant's Audio Excel DSP 16 support (SC-6000 and SC-6600) CONFIG_AEDSP16 Answer Y if you have a Gallant's Audio Excel DSP 16 card. This card - emulate an SBPro or a Microsoft Sound System card. - You must select one of the Sound Blaster or Microsoft Sound System - drivers before select this menu item. - Read the drivers/sound/lowlevel/README.aedsp16 file and the head of - drivers/sound/lowlevel/aedsp16.c to have more informations about - this driver and its configuration. - - If you are changing the card configuration, please, undefine all - the old Audio Excel parameters because leaving it defined while - selecting the alternate emulation, may screw up your .config file. - - !!!NOTE!!! - The driver supports Audio Excel DSP 16 but not the III version of - this card. Read drivers/sound/lowlevel/Readme.aedsp16 if you want - to know something more on how to use the III version with this sound - driver. + can emulate an SBPro or a Microsoft Sound System card, so you should + have said Y to either "SoundBlaster (SB, SBPro, SB16, clones) + support" or "Microsoft Sound System support", above, and you need to + answer the "MSS emulation" and "SBPro emulation" questions below + accordingly. You should say Y to one and only one of these + questions. Read the drivers/sound/lowlevel/README.aedsp16 file and + the head of drivers/sound/lowlevel/aedsp16.c to get more + information about this driver and its configuration. This driver + supports Audio Excel DSP 16 but not the III nor Pnp versions of this + card. Read drivers/sound/lowlevel/README.aedsp16 if you want to know + something more on how to use the III version with this sound driver. SC-6600 based audio cards (new Audio Excel DSP 16) CONFIG_SC6600 The SC6600 is the new version of DSP mounted on the Audio Excel DSP 16 - cards. Check the FCC ID of your audio card and answer Y if you have an - SC6600 DSP. + cards. Find in the manual the FCC ID of your audio card and answer Y if + you have an SC6600 DSP. Audio Excel DSP 16 (MSS emulation) CONFIG_AEDSP16_MSS - Answer Y if you want your audio card emulate Microsoft Sound System. + Answer Y if you want your audio card to emulate Microsoft Sound + System. You should then say Y to "Microsoft Sound System support" + and say N to "Audio Excel DSP 16 (SBPro emulation)". Audio Excel DSP 16 (SBPro emulation) CONFIG_AEDSP16_SBPRO - Answer Y if you want your audio card emulate Sound Blaster Pro. + Answer Y if you want your audio card to emulate Sound Blaster Pro. + You should then say Y to "SoundBlaster (SB, SBPro, SB16, clones) + support" and N to "Audio Excel DSP 16 (MSS emulation)". Kernel profiling support CONFIG_PROFILE @@ -5016,10 +5229,10 @@ flush the disks, reboot the system immediately or dump some status information). This is accomplished by pressing various keys while holding SysRq (Alt+PrintScreen). As you are expected to be a kernel - hacker to use this, the simple rule about learning what do the keys - mean is "Use the source, Luke!" -- read drivers/char/sysrq.c. - Don't say Y unless you really know what does this hack do. - + hacker to use this, the simple rule about learning what the keys + mean is "Use the source, Luke!" -- read drivers/char/sysrq.c. + Don't say Y unless you really know what this hack does. + ISDN subsystem CONFIG_ISDN ISDN ("Integrated Services Digital Networks", called RNIS in France) @@ -5032,10 +5245,10 @@ provider purchased an ISDN line from the phone company. For details, read http://alumni.caltech.edu/~dank/isdn/ on the WWW. (To browse the WWW, you need to have access to a machine on the Internet - that has one of the programs lynx, netscape or Mosaic.) This driver - allows you to use an ISDN-card for networking connections and as - dialin/out device. The isdn-tty's have a built in AT-compatible - modem emulator. Network devices support autodial, channel-bundling, + that has a program like lynx or netscape.) This driver allows you + to use an ISDN-card for networking connections and as dialin/out + device. The isdn-tty's have a built in AT-compatible modem + emulator. Network devices support autodial, channel-bundling, callback and caller-authentication without having a daemon running. A reduced T.70 protocol is supported with tty's suitable for German BTX. On D-Channel, the protocols EDSS1 and 1TR6 are @@ -5074,8 +5287,8 @@ (mgetty+sendfax by gert@greenie.muc.de with an extension, available with the ISDN utility package for example), you will be able to use your Linux box as an ISDN-answering machine. Of course, this must be - supported by the lowlevel driver also. Currently, the HiSax driver is - the only voice-supporting driver. See + supported by the lowlevel driver also. Currently, the HiSax driver + is the only voice-supporting driver. See Documentation/isdn/README.audio for more information. ICN 2B and 4B support @@ -5093,16 +5306,14 @@ HiSax SiemensChipSet driver support CONFIG_ISDN_DRV_HISAX - This is an alternative driver supporting the Siemens chipset on - various ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, - Teles S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and many - compatibles). It's a complete rewrite of the original Teles driver. - So you either say M or Y here and N in the above Teles section. If - you want to compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read Documentation/modules.txt. The module will be called - hisax.o. See Documentation/isdn/README.HiSax for further - informations on using this driver. + This is a driver supporting the Siemens chipset on various + ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, Teles + S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and many + compatibles). If you want to compile this as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called hisax.o. See Documentation/isdn/README.HiSax for + further informations on using this driver. HiSax Support for Teles 16.0/8.0 CONFIG_HISAX_16_0 @@ -5127,14 +5338,21 @@ using the different cards, a different D-channel protocol, or non-standard irq/port/shmem settings. -HiSax Support for Elsa cards +HiSax Support for Elsa ISA cards CONFIG_HISAX_ELSA_PCC - This enables HiSax support for the Elsa Mircolink cards and + This enables HiSax support for the Elsa Mircolink ISA cards and for the Elsa Quickstep series cards. See Documentation/isdn/README.HiSax on how to configure it using the different cards, a different D-channel protocol, or non-standard irq/port/shmem settings. +HiSax Support for Elsa PCMCIA card +CONFIG_HISAX_ELSA_PCMCIA + This enables HiSax support for the Elsa PCMCIA cards. + See Documentation/isdn/README.HiSax on how to configure it + using the different cards, a different D-channel protocol, or + non-standard irq/port/shmem settings. + HiSax Support for ITK ix1-micro Revision 2 CONFIG_HISAX_IX1MICROR2 This enables HiSax support for the ITK ix1-micro Revision 2 card. @@ -5149,6 +5367,11 @@ NOTE: This is mutually exclusive with HiSax Support for German 1TR6 if you have only one ISDN card installed. +HiSax Support for US/NI-1 +CONFIG_HISAX_NI1 + You should choose the D-channel protocol your local + telephone service provider uses here by saying Y or N. + HiSax Support for German 1TR6 CONFIG_HISAX_1TR6 You should choose the D-channel protocol your local @@ -5177,6 +5400,26 @@ called sc.o. See Documentation/isdn/README.sc and http://www.spellcast.com for more information. +AVM-B1 with CAPI2.0 support +CONFIG_ISDN_DRV_AVMB1 + This enables support for the AVM B1 ISDN networking cards. In + addition, a CAPI (Common ISDN Application Programming Interface, a + standard making it easy for programs to access ISDN hardware, see + http://www.capi.org/) interface for this card is provided. In order + to use this card, additional firmware is necessary, which has to be + downloaded into the card using a utility which is distributed + separately. Please read the file Documentation/isdn/README.avmb1. + 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 avmb1.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + +Verbose reason code reporting (kernel size +=7K) +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON + If you say Y here, the AVM B1 driver will give verbose reasons for + disconnecting. This will increase the size of the kernel by 7K. If + unsure, say Y. + Support for AP1000 multicomputer CONFIG_AP1000 This enables support for a sparc based parallel multi-computer @@ -5204,13 +5447,15 @@ Amiga support CONFIG_AMIGA This option enables support for the Amiga series of computers. If - you plan to use this kernel on an Amiga, say Y here; otherwise say N. + you plan to use this kernel on an Amiga, say Y here and browse the + material available in Documentation/m68k; otherwise say N. Atari support CONFIG_ATARI This option enables support for the 68000-based Atari series of computers (including the TT, Falcon and Medusa). If you plan to use - this kernel on an Atari, say Y here; otherwise say N. + this kernel on an Atari, say Y here and browse the material + available in Documentation/m68k; otherwise say N. Macintosh support CONFIG_MAC @@ -5728,4 +5973,20 @@ # LocalWords: wanrouter WANPIPE multiprotocol Mbps wanpipe EtherWORKS nodma SC # LocalWords: smp HiSax SiemensChipSet Siemens AVM Elsa ITK hisax PCC MICROR # LocalWords: Mircolink EURO DSS Spellcaster BRI sc spellcast Digiboards GPIO -# LocalWords: SYMBIOS COMPAT SDMS rev ASUS Tekram +# LocalWords: SYMBIOS COMPAT SDMS rev ASUS Tekram HX VX API ibmmcascsi ASY asy +# LocalWords: loader's PCnetPCI automounter AUTOFS amd autofs VT Gallant's Pnp +# LocalWords: AEDSP aedsp enskip tik Sysctl sysctl PARPORT parport pnp IDs EPP +# LocalWords: Autoprobe conformant bart patrickr HDLS READBACK AB usr DAMA DS +# LocalWords: Symbios PCscsi tmscsim RoamAbout GHz Hinds's contrib mathematik +# LocalWords: darmstadt okir DIGIEPCA International's Xem digiepca epca bootup +# LocalWords: zorro CAPI AVMB capi avmb VP SYN syncookies EM em pc Ethertalk +# LocalWords: Dayna DL Daynatalk LT PhoneNET ATB Daystar queueing CMDS SCBs ls +# LocalWords: SCB STATS Thinnet ThunderLAN TLAN Netelligent NetFlex tlan james +# LocalWords: caldera Preload dcache Preloading slowdowns schoebel uni +# LocalWords: stuttgart rdist TRANS hostnames mango jukeboxes ESS +# LocalWords: hardlinked NAMETRANS env mtab fstab umount nologin runlevel gid +# LocalWords: transname filespace adm Nodename hostname uname Kernelname bootp +# LocalWords: KERNNAME kname ktype kernelname Kerneltype KERNTYPE Alt SCB's RX +# LocalWords: dataless kerneltype SYSNAME Netbeui Comtrol Rocketport palmtop +# LocalWords: nvram SYSRQ SysRq PrintScreen sysrq NVRAMs NvRAM Shortwave RTTY +# LocalWords: HFMODEM shortwave Sitor Amtor Pactor GTOR hfmodem hayes TX TMOUT diff -u --recursive --new-file v2.1.50/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.50/linux/MAINTAINERS Mon Aug 4 16:25:35 1997 +++ linux/MAINTAINERS Sat Aug 16 09:51:46 1997 @@ -95,6 +95,13 @@ L: linux-net@vger.rutgers.edu S: Maintained +NI5010 NETWORK DRIVER +P: Jan-Pascal van Best and Andreas Mohr +M: jvbest@qv3pluto.leidenuniv.nl (Best) +M: 100.30936@germany.net (Mohr) +L: linux-net@vger.rutgers.edu +S: Maintained + TLAN NETWORK DRIVER P: James Banks M: james.banks@caldera.com @@ -259,9 +266,8 @@ S: Maintained MODULE SUPPORT [GENERAL], KERNELD -P: Bjorn Ekwall -M: bj0rn@blox.se -W: http://www.pi.se/blox/modules/ +P: Richard Henderson +M: richard@gnu.ai.mit.edu L: linux-kernel@vger.rutgers.edu S: Maintained diff -u --recursive --new-file v2.1.50/linux/Makefile linux/Makefile --- v2.1.50/linux/Makefile Thu Aug 14 20:49:16 1997 +++ linux/Makefile Sat Aug 16 09:53:08 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 50 +SUBLEVEL = 51 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) @@ -147,6 +147,10 @@ ifdef CONFIG_SBUS DRIVERS := $(DRIVERS) drivers/sbus/sbus.a +endif + +ifdef CONFIG_PPC +DRIVERS := $(DRIVERS) drivers/macintosh/macintosh.a endif ifdef CONFIG_PNP diff -u --recursive --new-file v2.1.50/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.50/linux/arch/i386/defconfig Mon Aug 4 16:25:35 1997 +++ linux/arch/i386/defconfig Sat Aug 16 10:05:22 1997 @@ -148,6 +148,8 @@ # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_MESH is not set +# CONFIG_SCSI_MAC53C94 is not set # # Network device support @@ -214,6 +216,7 @@ # CONFIG_ROMFS_FS is not set CONFIG_AUTOFS_FS=y # CONFIG_UFS_FS is not set +# CONFIG_MAC_PARTITION is not set # # Character devices diff -u --recursive --new-file v2.1.50/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.1.50/linux/arch/i386/kernel/i386_ksyms.c Thu May 29 21:53:04 1997 +++ linux/arch/i386/kernel/i386_ksyms.c Fri Aug 15 15:34:49 1997 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ EXPORT_SYMBOL_NOVERS(active_kernel_processor); EXPORT_SYMBOL(smp_invalidate_needed); EXPORT_SYMBOL_NOVERS(__lock_kernel); +EXPORT_SYMBOL(lk_lockmsg); /* Global SMP irq stuff */ EXPORT_SYMBOL(synchronize_irq); diff -u --recursive --new-file v2.1.50/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.1.50/linux/arch/i386/mm/fault.c Thu Jul 17 10:06:03 1997 +++ linux/arch/i386/mm/fault.c Sat Aug 16 22:14:24 1997 @@ -186,16 +186,15 @@ * * First we check if it was the bootup rw-test, though.. */ - if (wp_works_ok < 0 && address == 0xc0000000 && (error_code & 1)) { + if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & 1)) { wp_works_ok = 1; - pg0[0] = pte_val(mk_pte(0, PAGE_SHARED)); + pg0[0] = pte_val(mk_pte(TASK_SIZE, PAGE_SHARED)); flush_tlb(); goto out; } - if (address < PAGE_SIZE) { + if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); - pg0[0] = pte_val(mk_pte(0, PAGE_SHARED)); - } else + else printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at virtual address %08lx\n",address); __asm__("movl %%cr3,%0" : "=r" (page)); diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/Makefile linux/arch/m68k/kernel/Makefile --- v2.1.50/linux/arch/m68k/kernel/Makefile Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/Makefile Sat Aug 16 09:51:07 1997 @@ -13,7 +13,7 @@ all: kernel.o head.o O_TARGET := kernel.o O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \ - setup.o bios32.o sys_m68k.o time.o + setup.o sys_m68k.o time.o ifdef CONFIG_VT O_OBJS += console.o endif diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c --- v2.1.50/linux/arch/m68k/kernel/bios32.c Wed Dec 27 12:46:21 1995 +++ linux/arch/m68k/kernel/bios32.c Wed Dec 31 16:00:00 1969 @@ -1,7 +0,0 @@ -/* - * bios 32 replacement - */ -unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) -{ - return memory_start; -} diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.1.50/linux/arch/m68k/kernel/process.c Mon Aug 4 16:25:36 1997 +++ linux/arch/m68k/kernel/process.c Sat Aug 16 09:51:07 1997 @@ -65,7 +65,7 @@ current->priority = -100; current->counter = -100; for (;;){ - if (!need_resched) + if (!resched_needed()) #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) /* block out HSYNC on the atari (falcon) */ __asm__("stop #0x2200" : : : "cc"); diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.1.50/linux/arch/m68k/kernel/ptrace.c Sat May 24 09:10:22 1997 +++ linux/arch/m68k/kernel/ptrace.c Sat Aug 16 09:51:07 1997 @@ -526,7 +526,7 @@ goto out; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.1.50/linux/arch/m68k/kernel/signal.c Tue May 13 22:41:02 1997 +++ linux/arch/m68k/kernel/signal.c Sat Aug 16 09:51:07 1997 @@ -441,7 +441,7 @@ regs->pc -= 2; } } - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) { discard_frame: @@ -489,7 +489,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.1.50/linux/arch/mips/Makefile Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/Makefile Sat Aug 16 09:51:07 1997 @@ -13,29 +13,30 @@ # Copyright (C) 1994, 1995, 1996 by Ralf Baechle # DECStation modifications by Paul M. Antoine, 1996 # -# $Id: Makefile,v 1.7 1997/06/30 15:52:03 ralf Exp $ +# $Id: Makefile,v 1.8 1997/08/08 18:11:35 miguel Exp $ # # # Select the object file format to substitute into the linker script. # ifdef CONFIG_CPU_LITTLE_ENDIAN -CROSS_COMPILE = mipsel-linux- +CROSS_COMPILE = mipsel-linux- ifdef CONFIG_MIPS_ECOFF -oformat = ecoff-littlemips +oformat = ecoff-littlemips else -oformat = elf32-littlemips +oformat = elf32-littlemips endif else -CROSS_COMPILE = mips-linux- +CROSS_COMPILE = mips-linux- ifdef CONFIG_MIPS_ECOFF -oformat = ecoff-bigmips +oformat = ecoff-bigmips else -oformat = elf32-bigmips +oformat = elf32-bigmips endif endif LINKFLAGS = -static -N +MODFLAGS += -mlong-calls # # The new ELF GCC uses -G0 -mabicalls -fpic as default. We don't need PIC diff -u --recursive --new-file v2.1.50/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.1.50/linux/arch/mips/boot/Makefile Thu Jun 26 12:33:36 1997 +++ linux/arch/mips/boot/Makefile Sat Aug 16 09:51:07 1997 @@ -41,7 +41,6 @@ fi dep: - $(CPP) -M *.[cS] > .depend clean: rm -f zImage zImage.tmp mkboot diff -u --recursive --new-file v2.1.50/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.1.50/linux/arch/mips/config.in Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/config.in Sat Aug 16 09:51:07 1997 @@ -27,6 +27,9 @@ fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for SGI workstations' CONFIG_SGI + if [ "$CONFIG_SGI" = "y" ]; then + bool 'Support for SGI graphic devices' CONFIG_SGI_GRAPHICS + fi fi bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \ @@ -69,6 +72,7 @@ fi if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then define_bool CONFIG_BINFMT_IRIX y + define_bool CONFIG_FORWARD_KEYBOARD y fi define_bool CONFIG_BINFMT_ELF y define_bool CONFIG_BINFMT_AOUT n @@ -93,12 +97,7 @@ bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD fi -# -# All SGI block devices are SCSI based AFAIK. -davem -# -if [ "$CONFIG_SGI" != "y" ]; then - source drivers/block/Config.in -fi +source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then source net/Config.in @@ -215,3 +214,5 @@ int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi endmenu + +define_bool CONFIG_VGA_CONSOLE y diff -u --recursive --new-file v2.1.50/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.1.50/linux/arch/mips/defconfig Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/defconfig Sat Aug 16 09:51:07 1997 @@ -38,7 +38,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y CONFIG_SYSCTL=y -# CONFIG_PNP_PARPORT is not set +# CONFIG_PARPORT is not set # # Loadable module support @@ -133,6 +133,7 @@ # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set +# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set @@ -154,9 +155,6 @@ # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_DCACHE_PRELOAD is not set -# CONFIG_OMIRR is not set -# CONFIG_TRANS_NAMES is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y # CONFIG_FAT_FS is not set @@ -194,6 +192,7 @@ # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_JOYSTICK is not set # # Sound diff -u --recursive --new-file v2.1.50/linux/arch/mips/deskstation/hw-access.c linux/arch/mips/deskstation/hw-access.c --- v2.1.50/linux/arch/mips/deskstation/hw-access.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/hw-access.c Sat Aug 16 09:51:07 1997 @@ -5,10 +5,13 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: hw-access.c,v 1.2 1997/08/08 18:11:57 miguel Exp $ */ #include #include +#include #include #include #include @@ -194,3 +197,32 @@ rtc_write_data }; #endif + +static unsigned char dtc_read_input(void) +{ + return inb(KBD_DATA_REG); +} + +static void dtc_write_output(unsigned char val) +{ + outb(val, KBD_DATA_REG); +} + +static void dtc_write_command(unsigned char val) +{ + outb(val, KBD_CNTL_REG); +} + +static unsigned char dtc_read_status(void) +{ + return inb(KBD_STATUS_REG); +} + +static void dtc_rm200_keyboard_setup(void) +{ + kbd_read_input = dtc_read_input; + kbd_write_output = dtc_write_output; + kbd_write_command = dtc_write_command; + kbd_read_status = dtc_read_status; + request_region(0x60, 16, "keyboard"); +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c --- v2.1.50/linux/arch/mips/deskstation/setup.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/deskstation/setup.c Sat Aug 16 09:51:07 1997 @@ -6,6 +6,8 @@ * for more details. * * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: setup.c,v 1.2 1997/08/08 18:11:59 miguel Exp $ */ #include #include @@ -102,6 +104,7 @@ #endif } fd_cacheflush = deskstation_fd_cacheflush; + keyboard_setup = dtc_keyboard_setup; request_region(0x00,0x20,"dma1"); request_region(0x40,0x20,"timer"); request_region(0x70,0x10,"rtc"); diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/g364.c linux/arch/mips/jazz/g364.c --- v2.1.50/linux/arch/mips/jazz/g364.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/jazz/g364.c Sat Aug 16 09:51:07 1997 @@ -45,13 +45,13 @@ /* * Various defines for the G364 */ -#define G364_MEM_BASE 0xe0800000 -#define G364_PORT_BASE 0xe0200000 -#define ID_REG 0xe0200000 /* Read only */ -#define BOOT_REG 0xe0280000 -#define TIMING_REG 0xe0280108 /* to 0x080170 - DON'T TOUCH! */ -#define MASK_REG 0xe0280200 -#define CTLA_REG 0xe0280300 +#define G364_MEM_BASE 0xe4400000 +#define G364_PORT_BASE 0xe4000000 +#define ID_REG 0xe4000000 /* Read only */ +#define BOOT_REG 0xe4080000 +#define TIMING_REG 0xe4080108 /* to 0x080170 - DON'T TOUCH! */ +#define MASK_REG 0xe4080200 +#define CTLA_REG 0xe4080300 #define CURS_TOGGLE 0x800000 #define BIT_PER_PIX 0x700000 /* bits 22 to 20 of Control A */ #define DELAY_SAMPLE 0x080000 @@ -72,14 +72,14 @@ #define INTL_STAND 0x000004 #define SCRN_FORM 0x000002 #define ENABLE_VTG 0x000001 -#define TOP_REG 0xe0280400 -#define CURS_PAL_REG 0xe0280508 /* to 0x080518 */ -#define CHKSUM_REG 0xe0280600 /* to 0x080610 - unused */ -#define CURS_POS_REG 0xe0280638 -#define CLR_PAL_REG 0xe0280800 /* to 0x080ff8 */ -#define CURS_PAT_REG 0xe0281000 /* to 0x081ff8 */ -#define MON_ID_REG 0xe0300000 /* unused */ -#define RESET_REG 0xe0380000 /* Write only */ +#define TOP_REG 0xe4080400 +#define CURS_PAL_REG 0xe4080508 /* to 0x080518 */ +#define CHKSUM_REG 0xe4080600 /* to 0x080610 - unused */ +#define CURS_POS_REG 0xe4080638 +#define CLR_PAL_REG 0xe4080800 /* to 0x080ff8 */ +#define CURS_PAT_REG 0xe4081000 /* to 0x081ff8 */ +#define MON_ID_REG 0xe4100000 /* unused */ +#define RESET_REG 0xe4180000 /* Write only */ /* * built-in font management constants diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c --- v2.1.50/linux/arch/mips/jazz/hw-access.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/jazz/hw-access.c Sat Aug 16 09:51:07 1997 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle */ #include #include @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -146,3 +147,35 @@ rtc_read_data, rtc_write_data }; + +static volatile keyboard_hardware *jazz_kh = (keyboard_hardware *)JAZZ_KEYBOARD_ADDRESS; + +static unsigned char jazz_read_input(void) +{ + return jazz_kh->data; +} + +static void jazz_write_output(unsigned char val) +{ + jazz_kh->data = val; +} + +static void jazz_write_command(unsigned char val) +{ + jazz_kh->command = val; +} + +static unsigned char jazz_read_status(void) +{ + return jazz_kh->command; +} + +void jazz_keyboard_setup(void) +{ + kbd_read_input = jazz_read_input; + kbd_write_output = jazz_write_output; + kbd_write_command = jazz_write_command; + kbd_read_status = jazz_read_status; + request_region(0x60, 16, "keyboard"); + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | JAZZ_IE_KEYBOARD); +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c --- v2.1.50/linux/arch/mips/jazz/jazzdma.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/jazz/jazzdma.c Sat Aug 16 09:51:07 1997 @@ -514,3 +514,18 @@ return residual; } + +/* + * Get DMA channel enable register + */ +int vdma_get_enable(int channel) +{ + int enable; + + enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)); + + if (vdma_debug) + printk("vdma_get_enable: channel %d: enable=%d\n",channel,enable); + + return enable; +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.1.50/linux/arch/mips/jazz/setup.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/jazz/setup.c Sat Aug 16 09:51:07 1997 @@ -11,13 +11,16 @@ #include #include #include +#include #include +#include #include #include #include #include #include #include +#include /* * Initial irq handlers. @@ -32,6 +35,7 @@ extern asmlinkage void jazz_handle_int(void); extern asmlinkage void jazz_fd_cacheflush(const void *addr, size_t size); extern struct feature jazz_feature; +extern void jazz_keyboard_setup(void); extern void jazz_machine_restart(char *command); extern void jazz_machine_halt(void); @@ -94,8 +98,13 @@ } } + add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K); + add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M); + add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M); + irq_setup = jazz_irq_setup; fd_cacheflush = jazz_fd_cacheflush; + keyboard_setup = jazz_keyboard_setup; feature = &jazz_feature; // Will go away port_base = JAZZ_PORT_BASE; isa_slot_offset = 0xe3000000; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.1.50/linux/arch/mips/kernel/gdb-stub.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/kernel/gdb-stub.c Sat Aug 16 09:51:07 1997 @@ -12,7 +12,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-stub.c,v 1.4 1997/06/30 15:52:25 ralf Exp $ + * $Id: gdb-stub.c,v 1.5 1997/08/08 18:12:15 miguel Exp $ */ /* @@ -67,12 +67,14 @@ */ #include -#include #include +#include +#include +#include #include #include -#include +#include #include #include @@ -98,13 +100,11 @@ static void getpacket(char *buffer); static void putpacket(char *buffer); -static void set_mem_fault_trap(int enable); static int computeSignal(int tt); static int hex(unsigned char ch); static int hexToInt(char **ptr, int *intValue); static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); void handle_exception(struct gdb_regs *regs); -static void show_gdbregs(struct gdb_regs *regs); /* * BUFMAX defines the maximum number of characters in inbound/outbound buffers @@ -241,6 +241,21 @@ */ static volatile int mem_err = 0; + +#if 0 +static void set_mem_fault_trap(int enable) +{ + mem_err = 0; + +#if 0 + if (enable) + exceptionHandler(9, fltr_set_mem_err); + else + exceptionHandler(9, trap_low); +#endif +} +#endif /* dead code */ + /* * Convert the memory pointed to by mem into hex, placing result in buf. * Return a pointer to the last char put in buf (null), in case of mem fault, @@ -362,19 +377,6 @@ /* FIXME: Needs to be written... */ } - -static void set_mem_fault_trap(int enable) -{ - mem_err = 0; - -#if 0 - if (enable) - exceptionHandler(9, fltr_set_mem_err); - else - exceptionHandler(9, trap_low); -#endif -} - /* * Convert the MIPS hardware trap type code to a unix signal number. */ @@ -415,6 +417,38 @@ return (numChars); } + +#if 0 +/* + * Print registers (on target console) + * Used only to debug the stub... + */ +void show_gdbregs(struct gdb_regs * regs) +{ + /* + * Saved main processor registers + */ + printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg0, regs->reg1, regs->reg2, regs->reg3, + regs->reg4, regs->reg5, regs->reg6, regs->reg7); + printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg8, regs->reg9, regs->reg10, regs->reg11, + regs->reg12, regs->reg13, regs->reg14, regs->reg15); + printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg16, regs->reg17, regs->reg18, regs->reg19, + regs->reg20, regs->reg21, regs->reg22, regs->reg23); + printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + regs->reg24, regs->reg25, regs->reg26, regs->reg27, + regs->reg28, regs->reg29, regs->reg30, regs->reg31); + + /* + * Saved cp0 registers + */ + printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", + regs->cp0_epc, regs->cp0_status, regs->cp0_cause); +} +#endif /* dead code */ + /* * This function does all command processing for interfacing to gdb. It * returns 1 if you should skip the instruction at the trap address, 0 @@ -725,33 +759,4 @@ la $8,0x80000001 lw $9,0($8) "); -} - -/* - * Print registers (on target console) - * Used only to debug the stub... - */ -void show_gdbregs(struct gdb_regs * regs) -{ - /* - * Saved main processor registers - */ - printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg0, regs->reg1, regs->reg2, regs->reg3, - regs->reg4, regs->reg5, regs->reg6, regs->reg7); - printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg8, regs->reg9, regs->reg10, regs->reg11, - regs->reg12, regs->reg13, regs->reg14, regs->reg15); - printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg16, regs->reg17, regs->reg18, regs->reg19, - regs->reg20, regs->reg21, regs->reg22, regs->reg23); - printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - regs->reg24, regs->reg25, regs->reg26, regs->reg27, - regs->reg28, regs->reg29, regs->reg30, regs->reg31); - - /* - * Saved cp0 registers - */ - printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, regs->cp0_status, regs->cp0_cause); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h --- v2.1.50/linux/arch/mips/kernel/irix5sys.h Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/irix5sys.h Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: irix5sys.h,v 1.1 1997/06/06 09:32:29 ralf Exp $ +/* $Id: irix5sys.h,v 1.2 1997/08/08 18:12:17 miguel Exp $ * irix5sys.h: 32-bit IRIX5 ABI system call table. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.1.50/linux/arch/mips/kernel/irixioctl.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/irixioctl.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.1 1997/06/06 09:32:33 ralf Exp $ +/* $Id: irixioctl.c,v 1.2 1997/08/08 18:12:19 miguel Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.1.50/linux/arch/mips/kernel/irixsig.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/irixsig.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: irixsig.c,v 1.2 1997/06/13 10:11:22 ralf Exp $ +/* $Id: irixsig.c,v 1.4 1997/08/08 18:12:21 miguel Exp $ * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -142,7 +142,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -180,7 +180,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; @@ -593,7 +593,6 @@ #define P_ALL 7 extern int getrusage(struct task_struct *, int, struct rusage *); -extern void release(struct task_struct * p); #define W_EXITED 1 #define W_TRAPPED 2 @@ -680,7 +679,7 @@ REMOVE_LINKS(p); p->p_pptr = p->p_opptr; SET_LINKS(p); - notify_parent(p); + notify_parent(p, SIGCHLD); } else release(p); goto end_waitsys; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.1.50/linux/arch/mips/kernel/irq.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/kernel/irq.c Sat Aug 16 09:51:07 1997 @@ -11,7 +11,7 @@ * * Mips support by Ralf Baechle and Andreas Busse * - * $Id: irq.c,v 1.6 1997/06/30 15:52:34 ralf Exp $ + * $Id: irq.c,v 1.7 1997/08/08 18:12:24 miguel Exp $ */ #include #include @@ -51,6 +51,9 @@ static inline void mask_irq(unsigned int irq_nr) { unsigned char mask; + + if (irq_nr >= 16) + return; mask = 1 << (irq_nr & 7); if (irq_nr < 8) { @@ -65,6 +68,9 @@ static inline void unmask_irq(unsigned int irq_nr) { unsigned char mask; + + if (irq_nr >= 16) + return; mask = ~(1 << (irq_nr & 7)); if (irq_nr < 8) { diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.1.50/linux/arch/mips/kernel/mips_ksyms.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/mips_ksyms.c Sat Aug 16 09:51:07 1997 @@ -5,40 +5,69 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: mips_ksyms.c,v 1.2 1997/08/08 18:12:26 miguel Exp $ */ #include #include #include #include #include +#include + +#include #include #include #include +#include +#include +#include #include +#include EXPORT_SYMBOL(EISA_bus); /* * String functions */ +EXPORT_SYMBOL_NOVERS(bcopy); +EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(bcopy); +EXPORT_SYMBOL_NOVERS(strcat); +EXPORT_SYMBOL_NOVERS(strchr); +EXPORT_SYMBOL_NOVERS(strlen); +EXPORT_SYMBOL_NOVERS(strncat); +EXPORT_SYMBOL_NOVERS(strnlen); +EXPORT_SYMBOL_NOVERS(strrchr); +EXPORT_SYMBOL_NOVERS(strtok); +EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__mips_bh_counter); EXPORT_SYMBOL(local_irq_count); +/* + * Userspace access stuff. + */ +EXPORT_SYMBOL(__copy_user); +EXPORT_SYMBOL(active_ds); + /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); /* * Functions to control caches. */ +EXPORT_SYMBOL(flush_page_to_ram); EXPORT_SYMBOL(fd_cacheflush); /* * Base address of ports for Intel style I/O. */ EXPORT_SYMBOL(port_base); + +#ifdef CONFIG_SGI +EXPORT_SYMBOL(hpc3c0); +#endif diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.1.50/linux/arch/mips/kernel/ptrace.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/ptrace.c Sat Aug 16 09:51:07 1997 @@ -488,7 +488,7 @@ return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.1.50/linux/arch/mips/kernel/signal.c Mon Jul 7 08:18:53 1997 +++ linux/arch/mips/kernel/signal.c Sat Aug 16 09:51:07 1997 @@ -4,7 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996 Ralf Baechle * - * $Id: signal.c,v 1.7 1997/06/25 19:25:08 ralf Exp $ + * $Id: signal.c,v 1.8 1997/08/08 18:12:30 miguel Exp $ */ #include #include @@ -292,7 +292,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -332,7 +332,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.1.50/linux/arch/mips/kernel/syscall.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/syscall.c Sat Aug 16 09:51:07 1997 @@ -88,7 +88,7 @@ * possible. Should help alot for battery powered * R4200/4300i systems. */ - if (wait_available && !need_resched) + if (wait_available && !resched_needed()) __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0\n\t"); diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.1.50/linux/arch/mips/kernel/syscalls.h Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/syscalls.h Sat Aug 16 09:51:07 1997 @@ -5,9 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: syscalls.h,v 1.6 1997/07/20 15:32:25 ralf Exp $ + * $Id: syscalls.h,v 1.7 1997/08/08 18:12:32 miguel Exp $ */ /* @@ -208,5 +208,7 @@ SYS(sys_query_module, 5) SYS(sys_poll, 3) SYS(sys_nfsservctl, 3) +SYS(sys_setresgid, 3) /* 4190 */ +SYS(sys_getresgid, 3) SYS(sys_setresgid, 3) /* 4190 */ SYS(sys_getresgid, 3) diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.1.50/linux/arch/mips/kernel/sysirix.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/sysirix.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.3 1997/07/20 15:32:25 ralf Exp $ +/* $Id: sysirix.c,v 1.4 1997/08/08 18:12:35 miguel Exp $ * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller @@ -751,6 +751,8 @@ } error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -1514,6 +1516,8 @@ error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; @@ -1877,6 +1881,8 @@ error = 0; +dput_and_out: + dput(dentry); out: unlock_kernel(); return error; diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.1.50/linux/arch/mips/kernel/sysmips.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/kernel/sysmips.c Sat Aug 16 09:51:07 1997 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.5 1997/07/20 15:32:27 ralf Exp $ + * $Id: sysmips.c,v 1.6 1997/08/08 18:12:38 miguel Exp $ */ #include #include diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c --- v2.1.50/linux/arch/mips/kernel/time.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/kernel/time.c Sat Aug 16 09:51:07 1997 @@ -6,7 +6,7 @@ * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. * - * $Id: time.c,v 1.4 1997/06/30 15:52:40 ralf Exp $ + * $Id: time.c,v 1.5 1997/08/08 18:12:39 miguel Exp $ */ #include #include diff -u --recursive --new-file v2.1.50/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.1.50/linux/arch/mips/kernel/traps.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/kernel/traps.c Sat Aug 16 09:51:07 1997 @@ -196,6 +196,8 @@ /* * Assume it would be too dangerous to continue ... */ + printk ("BE HANDLER\n"); + show_regs (regs); force_sig(SIGBUS, current); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.1.50/linux/arch/mips/lib/Makefile Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/Makefile Sat Aug 16 09:51:07 1997 @@ -1,6 +1,12 @@ # # Makefile for MIPS-specific library files.. # +# Many of these routines are just left over debugging trash of ancient +# times when I just make my Tyne beep and so ... +# +# ...and for when I need to get the DECStation to use the boot prom to +# do things... Paul M. Antoine. +# .S.s: $(CPP) $(CFLAGS) $< -o $*.s @@ -8,8 +14,8 @@ $(CC) $(CFLAGS) -c $< -o $*.o L_TARGET = lib.a -L_OBJS = checksum.o copy_user.o csum.o dump_tlb.o io.o \ - memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o +L_OBJS = beep.o checksum.o copy_user.o csum.o dump_tlb.o io.o memset.o \ + memcpy.o strlen_user.o strncpy_user.o tags.o watch.o ifdef CONFIG_DECSTATION L_OBJS += pmaxcon.o pmaxio.o diff -u --recursive --new-file v2.1.50/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c --- v2.1.50/linux/arch/mips/lib/checksum.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/lib/checksum.c Sat Aug 16 09:51:07 1997 @@ -5,7 +5,7 @@ * * MIPS specific IP/TCP/UDP checksumming routines * - * Authors: Ralf Baechle, + * Authors: Ralf Baechle, * Lots of code moved from tcp.c and ip.c; see those files * for more names. * @@ -14,7 +14,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: checksum.c,v 1.4 1997/07/03 09:43:16 ralf Exp $ + * $Id: checksum.c,v 1.5 1997/08/08 18:12:51 miguel Exp $ */ #include #include diff -u --recursive --new-file v2.1.50/linux/arch/mips/lib/dump_tlb.c linux/arch/mips/lib/dump_tlb.c --- v2.1.50/linux/arch/mips/lib/dump_tlb.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/lib/dump_tlb.c Sat Aug 16 09:51:07 1997 @@ -16,12 +16,27 @@ #include #include +static char *region_map [] = { + "u", "s", "k", "!" +}; + +static char *cache_map [] = { + "c/nc/wt/nwa,", + "c/nc/wt/wa, ", + "uncached, ", + "c/nc/wb, " + "unknown, ", + "unknown, ", + "unknown, ", + "unknown, " +}; + void dump_tlb(int first, int last) { int i; int wired; - unsigned int pagemask; + unsigned int pagemask, c0, c1, r; unsigned long long entryhi, entrylo0, entrylo1; wired = read_32bit_cp0_register(CP0_WIRED); @@ -48,14 +63,25 @@ /* * Only print entries in use */ - printk("\nIndex: %2d %08x", i, pagemask); + printk("\nIndex: %2d pgmask=%08x ", i, pagemask); + + r = entryhi >> 62; + c0 = (entrylo0 >> 3) & 7; + c1 = (entrylo1 >> 3) & 7; - printk(" %08x %08x", (unsigned int)(entryhi >> 32), - (unsigned int) entryhi); - printk(" %08x %08x", (unsigned int)(entrylo0 >> 32), - (unsigned int) entrylo0); - printk(" %08x %08x", (unsigned int)(entrylo1 >> 32), - (unsigned int) entrylo1); + printk("%s vpn2=%08x " + "[pfn=%06x c=%d d=%d v=%d g=%d]" + "[pfn=%06x c=%d d=%d v=%d g=%d]", + region_map [r], (entryhi >> 13) & 0xffffffff, + (entrylo0 >> 6) & 0xffffff, c0, + (entrylo0 & 4) ? 1 : 0, + (entrylo0 & 2) ? 1 : 0, + (entrylo0 & 1), + (entrylo1 >> 6) & 0xffffff, c1, + (entrylo1 & 4) ? 1 : 0, + (entrylo1 & 2) ? 1 : 0, + (entrylo1 & 1)); + } } printk("\n"); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile --- v2.1.50/linux/arch/mips/mm/Makefile Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/mm/Makefile Sat Aug 16 09:51:07 1997 @@ -11,4 +11,8 @@ O_OBJS := extable.o init.o fault.o r4xx0.o r2300.o r6000.o tfp.o \ andes.o loadmmu.o +ifdef CONFIG_SGI +O_OBJS += umap.o +endif + include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.1.50/linux/arch/mips/mm/andes.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/mm/andes.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.1 1997/06/06 09:34:31 ralf Exp $ +/* $Id: andes.c,v 1.2 1997/08/08 18:13:01 miguel Exp $ * andes.c: MMU and cache operations for the R10000 (ANDES). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -79,6 +79,12 @@ { } +static void andes_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* XXX */ +} + void ld_mmu_andes(void) { flush_cache_all = andes_flush_cache_all; @@ -92,6 +98,8 @@ flush_tlb_mm = andes_flush_tlb_mm; flush_tlb_range = andes_flush_tlb_range; flush_tlb_page = andes_flush_tlb_page; + + add_wired_entry = andes_add_wired_entry; load_pgd = andes_load_pgd; pgd_init = andes_pgd_init; diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.1.50/linux/arch/mips/mm/fault.c Mon Aug 4 16:25:36 1997 +++ linux/arch/mips/mm/fault.c Sat Aug 16 09:51:07 1997 @@ -117,7 +117,8 @@ * terminate things with extreme prejudice. */ printk(KERN_ALERT "Unable to handle kernel paging request at virtual " - "address %08lx, epc == %08lx\n", address, regs->cp0_epc); + "address %08lx, epc == %08lx, ra == %08lx\n", + address, regs->cp0_epc, regs->regs[31]); die_if_kernel("Oops", regs, writeaccess); do_exit(SIGKILL); out: diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.1.50/linux/arch/mips/mm/loadmmu.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/mm/loadmmu.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: loadmmu.c,v 1.1 1997/06/06 09:34:51 ralf Exp $ +/* $Id: loadmmu.c,v 1.2 1997/08/08 18:13:05 miguel Exp $ * loadmmu.c: Setup cpu/cache specific function ptrs at boot time. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -41,6 +41,10 @@ unsigned long address, pte_t pte); void (*show_regs)(struct pt_regs *); + +void (*add_wired_entry)(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + asmlinkage void (*resume)(void *tsk); extern void ld_mmu_r2300(void); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.1.50/linux/arch/mips/mm/r2300.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/mm/r2300.c Sat Aug 16 09:51:07 1997 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300.c,v 1.2 1997/06/30 15:52:51 ralf Exp $ + * $Id: r2300.c,v 1.3 1997/08/08 18:13:06 miguel Exp $ */ #include @@ -245,6 +245,14 @@ (unsigned int) regs->cp0_cause); } +static void r2300_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* + * FIXME, to be done + */ +} + void ld_mmu_r2300(void) { clear_page = r2300_clear_page; @@ -267,6 +275,8 @@ update_mmu_cache = r2300_update_mmu_cache; show_regs = r2300_show_regs; + + add_wired_entry = r2300_add_wired_entry; flush_tlb_all(); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.1.50/linux/arch/mips/mm/r4xx0.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/mm/r4xx0.c Sat Aug 16 09:51:07 1997 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4xx0.c,v 1.4 1997/06/30 15:52:53 ralf Exp $ + * $Id: r4xx0.c,v 1.5 1997/08/08 18:13:07 miguel Exp $ */ #include @@ -1856,7 +1856,7 @@ set_entrylo1(0); BARRIER; - entry = 0; + entry = get_wired(); /* Blast 'em all away. */ while(entry < NTLB_ENTRIES) { @@ -1943,7 +1943,7 @@ int oldpid, newpid, idx; #ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); + printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); #endif newpid = (vma->vm_mm->context & 0xff); page &= (PAGE_MASK << 1); @@ -2122,6 +2122,37 @@ printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n", regs->cp0_epc, regs->cp0_status, regs->cp0_cause); } + +static void r4k_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + save_and_cli(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = (get_entryhi() & 0xff); + old_pagemask = get_pagemask(); + wired = get_wired(); + set_wired (wired + 1); + set_index (wired); + BARRIER; + set_pagemask (pagemask); + set_entryhi(entryhi); + set_entrylo0(entrylo0); + set_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + set_entryhi(old_ctx); + BARRIER; + set_pagemask (old_pagemask); + flush_tlb_all(); + restore_flags(flags); +} /* Detect and size the various r4k caches. */ static void probe_icache(unsigned long config) @@ -2567,6 +2598,8 @@ update_mmu_cache = r4k_update_mmu_cache; show_regs = r4k_show_regs; + + add_wired_entry = r4k_add_wired_entry; flush_cache_all(); write_32bit_cp0_register(CP0_WIRED, 0); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c --- v2.1.50/linux/arch/mips/mm/r6000.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/mm/r6000.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: r6000.c,v 1.1 1997/06/06 09:35:31 ralf Exp $ +/* $Id: r6000.c,v 1.2 1997/08/08 18:13:11 miguel Exp $ * r6000.c: MMU and cache routines for the R6000 processors. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -156,6 +156,12 @@ (unsigned int) regs->cp0_cause); } +static void r6000_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* XXX */ +} + void ld_mmu_r6000(void) { flush_cache_all = r6000_flush_cache_all; @@ -175,6 +181,8 @@ update_mmu_cache = r6000_update_mmu_cache; show_regs = r6000_show_regs; + + add_wired_entry = r6000_add_wired_entry; flush_cache_all(); flush_tlb_all(); diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c --- v2.1.50/linux/arch/mips/mm/tfp.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/mm/tfp.c Sat Aug 16 09:51:07 1997 @@ -1,4 +1,4 @@ -/* $Id: tfp.c,v 1.1 1997/06/06 09:35:39 ralf Exp $ +/* $Id: tfp.c,v 1.2 1997/08/08 18:13:13 miguel Exp $ * tfp.c: MMU and cache routines specific to the r8000 (TFP). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -79,6 +79,12 @@ { } +static void tfp_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + /* XXX */ +} + void ld_mmu_tfp(void) { flush_cache_all = tfp_flush_cache_all; @@ -93,9 +99,11 @@ flush_tlb_range = tfp_flush_tlb_range; flush_tlb_page = tfp_flush_tlb_page; + add_wired_entry = tfp_add_wired_entry; + load_pgd = tfp_load_pgd; pgd_init = tfp_pgd_init; - + flush_cache_all(); flush_tlb_all(); } diff -u --recursive --new-file v2.1.50/linux/arch/mips/mm/umap.c linux/arch/mips/mm/umap.c --- v2.1.50/linux/arch/mips/mm/umap.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/mm/umap.c Sat Aug 16 09:51:07 1997 @@ -0,0 +1,216 @@ +/* + * arch/mips/mm/umap.c + * + * (C) Copyright 1994 Linus Torvalds + * + * Changes: + * + * Modified from Linus source to removing active mappings from any + * task. This is required for implementing the virtual graphics + * interface for direct rendering on the SGI - miguel. + * + * Added a routine to map a vmalloc()ed area into user space, this one + * is required by the /dev/shmiq driver - miguel. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static inline void +remove_mapping_pte_range (pmd_t *pmd, unsigned long address, unsigned long size) +{ + pte_t *pte; + unsigned long end; + + if (pmd_none (*pmd)) + return; + if (pmd_bad (*pmd)){ + printk ("remove_graphics_pte_range: bad pmd (%08lx)\n", pmd_val (*pmd)); + pmd_clear (pmd); + return; + } + pte = pte_offset (pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t entry = *pte; + if (pte_present (entry)) + set_pte (pte, pte_modify (entry, PAGE_NONE)); + address += PAGE_SIZE; + pte++; + } while (address < end); + +} + +static inline void +remove_mapping_pmd_range (pgd_t *pgd, unsigned long address, unsigned long size) +{ + pmd_t *pmd; + unsigned long end; + + if (pgd_none (*pgd)) + return; + + if (pgd_bad (*pgd)){ + printk ("remove_graphics_pmd_range: bad pgd (%08lx)\n", pgd_val (*pgd)); + pgd_clear (pgd); + return; + } + pmd = pmd_offset (pgd, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + remove_mapping_pte_range (pmd, address, end - address); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); + +} + +/* + * This routine is called from the page fault handler to remove a + * range of active mappings at this point + */ +void +remove_mapping (struct task_struct *task, unsigned long start, unsigned long end) +{ + unsigned long beg = start; + pgd_t *dir; + + down (&task->mm->mmap_sem); + dir = pgd_offset (task->mm, start); + flush_cache_range (task->mm, beg, end); + while (start < end){ + remove_mapping_pmd_range (dir, start, end - start); + start = (start + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_range (task->mm, beg, end); + up (&task->mm->mmap_sem); +} + +void *vmalloc_uncached (unsigned long size) +{ + return vmalloc_prot (size, PAGE_KERNEL_UNCACHED); +} + +static inline void free_pte(pte_t page) +{ + if (pte_present(page)) { + unsigned long addr = pte_page(page); + if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr))) + return; + free_page(addr); + if (current->mm->rss <= 0) + return; + current->mm->rss--; + return; + } + swap_free(pte_val(page)); +} + +static inline void forget_pte(pte_t page) +{ + if (!pte_none(page)) { + printk("forget_pte: old mapping existed!\n"); + free_pte(page); + } +} + +/* + * maps a range of vmalloc()ed memory into the requested pages. the old + * mappings are removed. + */ +static inline void +vmap_pte_range (pte_t *pte, unsigned long address, unsigned long size, unsigned long vaddr) +{ + unsigned long end; + pgd_t *vdir; + pmd_t *vpmd; + pte_t *vpte; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t oldpage = *pte; + unsigned long page; + pte_clear(pte); + + vdir = pgd_offset_k (vaddr); + vpmd = pmd_offset (vdir, vaddr); + vpte = pte_offset (vpmd, vaddr); + page = pte_page (*vpte); + + set_pte(pte, mk_pte_phys(page, PAGE_USERIO)); + forget_pte(oldpage); + address += PAGE_SIZE; + vaddr += PAGE_SIZE; + pte++; + } while (address < end); +} + +static inline int +vmap_pmd_range (pmd_t *pmd, unsigned long address, unsigned long size, unsigned long vaddr) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + vaddr -= address; + do { + pte_t * pte = pte_alloc(pmd, address); + if (!pte) + return -ENOMEM; + vmap_pte_range(pte, address, end - address, address + vaddr); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); + return 0; +} + +int +vmap_page_range (unsigned long from, unsigned long size, unsigned long vaddr) +{ + int error = 0; + pgd_t * dir; + unsigned long beg = from; + unsigned long end = from + size; + + vaddr -= from; + dir = pgd_offset(current->mm, from); + flush_cache_range(current->mm, beg, end); + while (from < end) { + pmd_t *pmd = pmd_alloc(dir, from); + error = -ENOMEM; + if (!pmd) + break; + error = vmap_pmd_range(pmd, from, end - from, vaddr + from); + if (error) + break; + from = (from + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_range(current->mm, beg, end); + return error; +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.1.50/linux/arch/mips/sgi/kernel/setup.c Mon Jul 7 08:18:54 1997 +++ linux/arch/mips/sgi/kernel/setup.c Sat Aug 16 09:51:08 1997 @@ -1,7 +1,9 @@ -/* $Id: setup.c,v 1.2 1997/06/30 15:26:24 ralf Exp $ +/* * setup.c: SGI specific setup, including init of the feature struct. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: setup.c,v 1.3 1997/08/08 18:13:22 miguel Exp $ */ #ifndef __GOGOGO__ #error "... about to fuckup your Indy?" @@ -9,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -26,6 +30,36 @@ struct feature sgi_feature = { }; +static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); + +static unsigned char sgi_read_input(void) +{ + return sgi_kh->data; +} + +static void sgi_write_output(unsigned char val) +{ + sgi_kh->data = val; +} + +static void sgi_write_command(unsigned char val) +{ + sgi_kh->command = val; +} + +static unsigned char sgi_read_status(void) +{ + return sgi_kh->command; +} + +static void sgi_keyboard_setup(void) +{ + kbd_read_input = sgi_read_input; + kbd_write_output = sgi_write_output; + kbd_write_command = sgi_write_command; + kbd_read_status = sgi_read_status; +} + static void sgi_irq_setup(void) { sgint_init(); @@ -52,6 +86,7 @@ irq_setup = sgi_irq_setup; feature = &sgi_feature; + keyboard_setup = sgi_keyboard_setup; _machine_restart = sgi_machine_restart; _machine_halt = sgi_machine_halt; diff -u --recursive --new-file v2.1.50/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c --- v2.1.50/linux/arch/mips/sni/hw-access.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sni/hw-access.c Sat Aug 16 09:51:08 1997 @@ -5,9 +5,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1997 by Ralf Baechle + * + * $Id: hw-access.c,v 1.2 1997/08/08 18:13:27 miguel Exp $ */ #include +#include #include #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -157,3 +161,32 @@ rtc_read_data, rtc_write_data }; + +static unsigned char sni_read_input(void) +{ + return inb(KBD_DATA_REG); +} + +static void sni_write_output(unsigned char val) +{ + outb(val, KBD_DATA_REG); +} + +static void sni_write_command(unsigned char val) +{ + outb(val, KBD_CNTL_REG); +} + +static unsigned char sni_read_status(void) +{ + return inb(KBD_STATUS_REG); +} + +void sni_rm200_keyboard_setup(void) +{ + kbd_read_input = sni_read_input; + kbd_write_output = sni_write_output; + kbd_write_command = sni_write_command; + kbd_read_status = sni_read_status; + request_region(0x60, 16, "keyboard"); +} diff -u --recursive --new-file v2.1.50/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.1.50/linux/arch/mips/sni/setup.c Thu Jun 26 12:33:38 1997 +++ linux/arch/mips/sni/setup.c Sat Aug 16 09:51:08 1997 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ extern asmlinkage void sni_rm200_pci_handle_int(void); extern asmlinkage void sni_fd_cacheflush(const void *addr, size_t size); extern struct feature sni_rm200_pci_feature; +extern void sni_rm200_keyboard_setup(void); extern void sni_machine_restart(char *command); extern void sni_machine_halt(void); @@ -127,6 +129,7 @@ fd_cacheflush = sni_fd_cacheflush; // Will go away feature = &sni_rm200_pci_feature; port_base = SNI_PORT_BASE; + keyboard_setup = sni_rm200_keyboard_setup; /* * Setup (E)ISA I/O memory access stuff diff -u --recursive --new-file v2.1.50/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.1.50/linux/arch/ppc/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/Makefile Sat Aug 16 09:51:08 1997 @@ -12,29 +12,30 @@ # # Copyright (C) 1994 by Linus Torvalds # Changes for PPC by Gary Thomas -# Modified by Cort Dougan +# Modified by Cort Dougan and Paul Mackerras # +ifeq ($(CONFIG_PMAC),y) +KERNELBASE =0xc0000000 +else +KERNELBASE =0x90000000 +endif + # PowerPC (cross) tools -SUFFIX = -AS = as$(SUFFIX) -ASFLAGS = -LD = ld$(SUFFIX) -LINKFLAGS = -T arch/ppc/ld.script -Ttext 0x90000000 -HOSTCC = gcc -CC = gcc$(SUFFIX) +ifneq ($(shell uname -m),ppc) +CROSS_COMPILE =powerpc-eabi- +endif + +ASFLAGS = +LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELBASE) -Bstatic CFLAGSINC = -D__KERNEL__ -I$(TOPDIR)/include -D__powerpc__ CFLAGS = $(CFLAGSINC) \ - -Wstrict-prototypes -fomit-frame-pointer \ + -Wall -Wstrict-prototypes -Wno-uninitialized \ -fno-builtin \ - -finhibit-size-directive \ - -O2 -fsigned-char -pipe -ffixed-r2 -mstring -mmultiple -msoft-float -# -fverbose-asm + -fsigned-char \ + -msoft-float \ + -O2 -pipe CPP = $(CC) -E $(CFLAGS) -AR = ar$(SUFFIX) -RANLIB = ranlib$(SUFFIX) -STRIP = strip$(SUFFIX) -NM = nm$(SUFFIX) ifdef CONFIG_601 CFLAGS := $(CFLAGS) -mcpu=601 -DCPU=601 @@ -55,59 +56,38 @@ ARCHIVES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(ARCHIVES) CORE_FILES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(CORE_FILES) +ifdef CONFIG_XMON +SUBDIRS += arch/ppc/xmon +CORE_FILES += arch/ppc/xmon/x.o +endif + +ifdef CONFIG_PMAC +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/coffboot +else +# PReP systems MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +endif checks: @$(MAKE) -C arch/$(ARCH)/kernel checks -netboot: checks vmlinux - @$(MAKEBOOT) netboot - -znetboot: checks vmlinux - @$(MAKEBOOT) znetboot - -#rcpboot: checks vmlinux -# @$(MAKEBOOT) rcpboot +BOOT_TARGETS = netboot znetboot zImage floppy install \ + vmlinux.coff znetboot.initrd zImage.initrd -zImage: checks vmlinux - @$(MAKEBOOT) zImage +$(BOOT_TARGETS): checks vmlinux + @$(MAKEBOOT) $@ -floppy: checks vmlinux - @$(MAKEBOOT) floppy - -install: checks vmlinux - @$(MAKEBOOT) install - -vmlinux.coff : checks vmlinux - $(MAKE) -C arch/ppc/coffboot/ vmlinux.coff - -arch/ppc/kernel: dummy - $(MAKE) linuxsubdirs SUBDIRS=arch/ppc/kernel - -arch/ppc/mm: dummy - $(MAKE) linuxsubdirs SUBDIRS=arch/ppc/mm - -arch/ppc/lib: dummy - $(MAKE) linuxsubdirs SUBDIRS=arch/ppc/lib - -diffs: - arch/ppc/mkdiff - -tar: - arch/ppc/mktar +tags: + etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h} archclean: - rm -f arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h arch/ppc/kernel/checks TAGS - rm -f `find arch/ppc/ \( -name '*.[oas]' -o -name '*~' -o -name '#*#' \) -print` - rm -f `find include/asm-ppc/ \( -name '*.[oas]' -o -name '*~' -o -name '#*#' \) -print` + rm -f arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h + rm -f arch/ppc/kernel/checks + find arch/ppc/ -name '*.o' -exec /bin/rm -f '{}' \; + find arch/ppc/ -name '*~' -exec /bin/rm -f '{}' \; + find arch/ppc/ -name '*.a' -exec /bin/rm -f '{}' \; @$(MAKEBOOT) clean archdep: - $(MAKE) -C arch/ppc/boot fastdep - $(MAKE) -C arch/ppc/kernel fastdep - $(MAKE) -C arch/ppc/mm fastdep - $(MAKE) -C arch/ppc/lib fastdep - -tags : - etags arch/ppc/*/*.c arch/ppc/*/*.S include/asm/* */*.c + $(MAKEBOOT) fastdep diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.1.50/linux/arch/ppc/boot/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/Makefile Sat Aug 16 09:51:08 1997 @@ -22,14 +22,15 @@ $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $< -ZLINKFLAGS = -T ../ld.script -Ttext 0x00800000 +ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000 GZIP_FLAGS = -v9 SYSTEM = $(TOPDIR)/vmlinux - -OBJECTS = head.o inflate.o unzip.o misc.o vreset.o - +OBJECTS = head.o inflate.o unzip.o misc.o vreset.o #kbd.o CFLAGS = -O2 -DSTDC_HEADERS -I$(TOPDIR)/include +OBJCOPY = objcopy +OBJCOPY_ARGS = -O elf32-powerpc + all: $(TOPDIR)/zImage @@ -39,41 +40,40 @@ find_name : find_name.c $(HOSTCC) $(CFLAGSINC) -o find_name find_name.c -mk_type41: mk_type41.c - $(HOSTCC) $(CFLAGSINC) -o mk_type41 mk_type41.c - -piggyback: piggyback.c - $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c - floppy: $(TOPDIR)/vmlinux zImage dd if=$(TOPDIR)/zImage of=/dev/fd0H1440 bs=64b -netboot : $(TOPDIR)/vmlinux mkprep - mkprep $(TOPDIR)/vmlinux $(TOPDIR)/netboot +floppy.initrd: $(TOPDIR)/vmlinux zImage + dd if=$(TOPDIR)/zImage.initrd of=/dev/fd0H1440 bs=64b -znetboot : zvmlinux mkprep - mkprep zvmlinux $(TOPDIR)/znetboot - cp $(TOPDIR)/znetboot /usr/local/tftpboot/vmlinux +znetboot : zImage mkprep + cp $(TOPDIR)/zImage /usr/local/tftpboot/vmlinux -rcpboot : znetboot - rcp $(TOPDIR)/znetboot charon:/usr/tftpboot/vmlinux +znetboot.initrd : zImage.initrd mkprep + cp $(TOPDIR)/zImage.initrd /usr/local/tftpboot/vmlinux zImage: zvmlinux mkprep mkprep -pbp zvmlinux $(TOPDIR)/zImage -install: zImage - dd if=$(TOPDIR)/zImage of=/dev/sda4 - ln -s /dev/sda4 $(INSTALL_PATH)/vmlinuz - cp $(TOPDIR)/System.map $(INSTALL_PATH)/ - -zvmlinux: $(OBJECTS) $(SYSTEM) mkprep find_name - mkprep $(TOPDIR)/vmlinux -|gzip ${GZIP_FLAGS}|mkprep -asm - -|$(AS) -o piggy.o - $(LD) $(ZLINKFLAGS) -o zvmlinux $(OBJECTS) piggy.o - rm -f piggy.o +zImage.initrd: zvmlinux.initrd mkprep + mkprep -pbp zvmlinux.initrd $(TOPDIR)/zImage.initrd + +zvmlinux: $(OBJECTS) $(SYSTEM) mkprep find_name vmlinux.gz + $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz \ + zvmlinux.tmp $@ + rm zvmlinux.tmp + +vmlinux.gz: $(TOPDIR)/vmlinux + dd bs=64k skip=1 if=$(TOPDIR)/vmlinux | gzip -vf9 - > vmlinux.gz + +zvmlinux.initrd: zvmlinux + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz \ + zvmlinux $@ clean: - rm -f piggyback zvmlinux mk_type41 mkprep mkboot find_name - rm -f $(TOPDIR)/{zImage,znetboot,netboot} + rm -f vmlinux* znetboot* zImage* zvmlinux* mkprep find_name + rm -f $(TOPDIR)/{zImage*,znetboot*,zvmlinux*,vmlinux*} fastdep: $(TOPDIR)/scripts/mkdep *.[Sch] > .depend diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S --- v2.1.50/linux/arch/ppc/boot/head.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/head.S Sat Aug 16 09:51:08 1997 @@ -13,17 +13,6 @@ start: bl start_ start_: -/* TEMP - No residual data on BeBox (yet) */ -#if 0 -#define IS_BE_BOX 0x42654278 /* 'BeBx' */ - lis r2,IS_BE_BOX>>16 - ori r2,r2,IS_BE_BOX&0xFFFF - cmp 0,r30,r2 - bne notBeBox - li r3,0 -#endif -notBeBox: -/* TEMP */ mr r11,r3 /* Save pointer to residual data */ mfmsr r3 /* Turn off interrupts */ li r4,0 @@ -48,7 +37,9 @@ mtlr r21 mtctr r22 bctr /* Jump to code */ -/* Relocate code to final resting spot */ +/* + * no matter where we're loaded, move ourselves to -Ttext address + */ relocate: mflr r3 /* Compute code bias */ subi r3,r3,4 @@ -98,13 +89,26 @@ mr r5,r6 /* Checksum */ mr r6,r11 /* Residual data */ bl decompress_kernel - /*mr r29,r3*/ /* R3 = TotalMemory */ - /*lis r28,hold_residual@h - ori r28,r28,hold_residual@l*/ + /* changed to use r3 (as firmware does) for kernel as ptr to residual -- Cort*/ - li r5,0x100 /* Kernel code starts here */ - mtlr r5 + lis r6,cmd_line@h + ori r6,r6,cmd_line@l + subi r7,r7,1 +00: lbzu r2,1(r12) + cmpi 0,r2,0 + bne 00b + + /* r4,r5 have initrd_start, size */ + lis r2,initrd_start@h + ori r2,r2,initrd_start@l + lwz r4,0(r2) + lis r2,initrd_end@h + ori r2,r2,initrd_end@l + lwz r5,0(r2) + + li r9,0x00c /* Kernel code starts here */ + mtlr r9 blr hang: b hang @@ -141,6 +145,45 @@ mtspr HID0,r3 blr +/* + * Delay for a number of microseconds + * -- Use the BUS timer (assumes 66MHz) + */ + .globl udelay +udelay: + mfspr r4,PVR + srwi r4,r4,16 + cmpi 0,r4,1 /* 601 ? */ + bne .udelay_not_601 +00: li r0,86 /* Instructions / microsecond? */ + mtctr r0 +10: addi r0,r0,0 /* NOP */ + bdnz 10b + subic. r3,r3,1 + bne 00b + blr + +.udelay_not_601: + mulli r4,r3,1000 /* nanoseconds */ + addi r4,r4,59 + li r5,60 + divw r4,r4,r5 /* BUS ticks */ +1: mftbu r5 + mftb r6 + mftbu r7 + cmp 0,r5,r7 + bne 1b /* Get [synced] base time */ + addc r9,r6,r4 /* Compute end time */ + addze r8,r5 +2: mftbu r5 + cmp 0,r5,r8 + blt 2b + bgt 3f + mftb r6 + cmp 0,r6,r9 + blt 2b +3: blr + /* * This space [buffer] is used to forceably flush the data cache when * running in copyback mode. This is necessary IFF the data cache could diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c --- v2.1.50/linux/arch/ppc/boot/misc.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/misc.c Sat Aug 16 09:51:08 1997 @@ -8,13 +8,23 @@ * puts by Nick Holloway 1993 * * Adapted for PowerPC by Gary Thomas + * Updated and modified by Cort Dougan (cort@cs.nmt.edu) */ #include "gzip.h" #include "lzw.h" #include "asm/residual.h" +#include RESIDUAL hold_residual; +unsigned long initrd_start = 0, initrd_end = 0; +char *zimage_start; +int zimage_size; +extern char input_data[]; +extern int input_len; +void cksum_text(void); +void verify_data(unsigned long load_addr); + void dump_buf(unsigned char *p, int s); #define EOF -1 @@ -26,8 +36,7 @@ unsigned insize; unsigned inptr; -extern char input_data[]; -extern int input_len; +char cmd_line[256]; int input_ptr; @@ -56,6 +65,9 @@ int orig_x, orig_y; void puts(const char *); +void putc(const char c); +void puthex(unsigned long val); +void _bcopy(char *src, char *dst, int len); void *malloc(int size) { @@ -77,7 +89,7 @@ */ if (free_mem_ptr < (long)&end) { - if (free_mem_ptr > (long)&input_data[input_ptr]) + if (free_mem_ptr > (long)&zimage_start[input_ptr]) error("\nOut of memory\n"); return p; @@ -87,7 +99,7 @@ #endif return p; puts("large kernel, low 1M tight..."); - free_mem_ptr = (long)input_data; + free_mem_ptr = (long)zimage_start; } } @@ -114,6 +126,53 @@ for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) vidmem[i] = ' '; } +#if 0 +tstc(void) +{ + return (CRT_tstc() ); +} + +getc(void) +{ + while (1) { + if (CRT_tstc()) return (CRT_getc()); + } +} +#endif +void +putc(const char c) +{ + int x,y; + + x = orig_x; + y = orig_y; + + if ( c == '\n' ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } else if (c == '\b') { + if (x > 0) { + x--; + } + } else { + vidmem [ ( x + cols * y ) * 2 ] = c; + if ( ++x >= cols ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } + } + + cursor(x, y); + + orig_x = x; + orig_y = y; +} void puts(const char *s) { @@ -229,10 +288,10 @@ insize = 0; do { len = INBUFSIZ-insize; - if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1; + if (len > (zimage_size-input_ptr+1)) len=zimage_size-input_ptr+1; if (len == 0 || len == EOF) break; - for (i=0;iTotalMemory; - } else { - TotalMemory = 0x01000000; + _bcopy((char *)residual, (char *)&hold_residual, sizeof(hold_residual)); + puts("Residual data at: "); puthex((unsigned long)residual); puts(" "); + puthex((unsigned long)(residual->ResidualLength + residual)); puts("\n"); } - puts("Uncompressing Linux..."); + /* + * Take care of initrd if we have one + */ + /* + * the _actual_ load addr is 64k (elf hdr size) lower but the + * firmware gives us the starting exec point not the load ptr + * -- Cort + */ + eh = (Elf32_Ehdr *)(load_addr - 65536); + sh = (Elf32_Shdr *)((unsigned long)eh + eh->e_shoff ); + /*puts("Entry point: "); puthex(eh->e_entry); puts("\n");*/ + + /* find string table */ + for ( i = 0 ; i <= eh->e_shnum ; i++,sh++) + { + /*puts("Section: "); puthex(i); + puts(" type: "); puthex(sh->sh_type); + puts(" offset: "); puthex(sh->sh_offset); + puts("\n");*/ + + if ( sh->sh_type == SHT_STRTAB ) + { + strtab_shdr = sh; + strtab = (char *)(sh->sh_offset + (unsigned long)eh); + /*puts("Found strtab at: "); puthex((unsigned long)strtab); + puts("\n");*/ + break; + } + } - method = get_method(0); + /* find the initrd and image sections */ + if ( strtab_shdr ) + { + sh = (Elf32_Shdr *)((unsigned long)eh + eh->e_shoff ); + for ( i = 0 ; i <= eh->e_shnum ; i++,sh++) + { + if ( !memcmp("initrd", (char *)(strtab+sh->sh_name), 6 ) ) + { + initrd_start = (unsigned long)eh + sh->sh_offset; + initrd_end = initrd_start + sh->sh_size; + puts("Found initrd at: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); + puts("\n"); + } + if ( !memcmp("image", (char *)(strtab+sh->sh_name), 5 ) ) + { + zimage_start = (char *)((unsigned long)eh + sh->sh_offset); + zimage_size = sh->sh_size; + puts("Found zimage at: "); puthex((unsigned long)zimage_start); + puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); + puts("\n"); + } + } + } + else + { + puts("Couldn't find string table for boot image!\n"); + } + + /* relocate initrd */ + if ( initrd_start ) + { + memcpy ((void *)0x00D00000,(void *)initrd_start, + initrd_end - initrd_start ); + initrd_end = 0x00D00000 + initrd_end - initrd_start; + initrd_start = 0x00D00000; + puts("Moved initrd to: "); puthex(initrd_start); + puts(" "); puthex(initrd_end); puts("\n"); + } + /* make the moto firmware print something */ + + puts("Uncompressing Linux..."); + method = get_method(0); work(0, 0); - puts("done.\n"); + puts("Now booting the kernel\n"); - /*return (TotalMemory);*/ /* Later this can be a pointer to saved residual data */ - return &hold_residual; + return (unsigned long)&hold_residual; } show_residual_data(RESIDUAL *res) { puts("Residual data: "); puthex(res->ResidualLength); puts(" bytes\n"); - puts("Total memory: "); puthex(res->TotalMemory); puts("\n"); #if 0 puts("Residual structure = "); puthex(sizeof(*res)); puts(" bytes\n"); dump_buf(&hold_residual, 32); @@ -407,14 +542,14 @@ { unsigned int *ptr, len, cksum, cnt; cksum = cnt = 0; - ptr = input_data; + ptr = (unsigned int *)zimage_start; puts("Checksums: "); - for (len = 0; len < input_len; len += 4) { + for (len = 0; len < zimage_size; len += 4) { cksum ^= *ptr++; if (len && ((len & 0x0FFF) == 0)) { if (cnt == 0) { puts("\n ["); - puthex(ptr-1); + puthex((unsigned long)ptr-1); puts("] "); } puthex(cksum); @@ -429,7 +564,7 @@ puts("Data cksum = "); puthex(cksum); puts("\n"); } -cksum_text() +void cksum_text(void) { extern int start, etext; unsigned int *ptr, len, text_len, cksum, cnt; @@ -442,7 +577,7 @@ if (len && ((len & 0x0FFF) == 0)) { if (cnt == 0) { puts("\n ["); - puthex(ptr-1); + puthex((unsigned long)ptr-1); puts("] "); } puthex(cksum); @@ -457,24 +592,24 @@ puts("TEXT cksum = "); puthex(cksum); puts("\n"); } -verify_data(unsigned long load_addr) +void verify_data(unsigned long load_addr) { extern int start, etext; unsigned int *orig_ptr, *copy_ptr, len, errors; errors = 0; - copy_ptr = input_data; - orig_ptr = (unsigned int *)(load_addr + ((unsigned int)input_data - (unsigned int)&start)); - for (len = 0; len < input_len; len += 4) { + copy_ptr = (unsigned int *)zimage_start; + orig_ptr = (unsigned int *)(load_addr + ((unsigned int)zimage_start - (unsigned int)&start)); + for (len = 0; len < zimage_size; len += 4) { if (*copy_ptr++ != *orig_ptr++) { errors++; } } - copy_ptr = input_data; - orig_ptr = (unsigned int *)(load_addr + ((unsigned int)input_data - (unsigned int)&start)); - for (len = 0; len < input_len; len += 4) { + copy_ptr = (unsigned int *)zimage_start; + orig_ptr = (unsigned int *)(load_addr + ((unsigned int)zimage_start - (unsigned int)&start)); + for (len = 0; len < zimage_size; len += 4) { if (*copy_ptr++ != *orig_ptr++) { - dump_buf(copy_ptr-1, 128); - dump_buf(orig_ptr-1, 128); + dump_buf((unsigned char *) (copy_ptr-1), 128); + dump_buf((unsigned char *) (orig_ptr-1), 128); puts("Total errors = "); puthex(errors*4); puts("\n"); while (1) ; } @@ -486,9 +621,9 @@ extern int start, etext; unsigned int *orig_ptr, *copy_ptr, len, errors; errors = 0; - copy_ptr = input_data; - orig_ptr = (unsigned int *)(load_addr + ((unsigned int)input_data - (unsigned int)&start)); - for (len = 0; len < input_len; len += 4) { + copy_ptr = (unsigned int *)zimage_start; + orig_ptr = (unsigned int *)(load_addr + ((unsigned int)zimage_start - (unsigned int)&start)); + for (len = 0; len < zimage_size; len += 4) { if (*copy_ptr++ != *orig_ptr++) { errors++; } @@ -532,7 +667,7 @@ } while (s > 0) { - puthex(p); puts(": "); + puthex((unsigned long)p); puts(": "); for (i = 0; i < 16; i++) { if (i < s) diff -u --recursive --new-file v2.1.50/linux/arch/ppc/boot/mkprep.c linux/arch/ppc/boot/mkprep.c --- v2.1.50/linux/arch/ppc/boot/mkprep.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/boot/mkprep.c Sat Aug 16 09:51:08 1997 @@ -131,17 +131,18 @@ argptr++; /* skip elf header in input file */ - lseek(in_fd, elfhdr_size, SEEK_SET); + if ( !prep ) + lseek(in_fd, elfhdr_size, SEEK_SET); /* write prep partition if necessary */ if ( prep ) - write_prep_partition( in_fd, out_fd ); + write_prep_partition( in_fd, out_fd ); /* write input image to bootimage */ if ( asmoutput ) - write_asm_data( in_fd, out_fd ); + write_asm_data( in_fd, out_fd ); else - copy_image(in_fd, out_fd); + copy_image(in_fd, out_fd); return 0; } @@ -161,28 +162,11 @@ } bzero( block, sizeof block ); - - /* set entry point and boot image size */ - *entry = cpu_to_le32(0x400); - /* need use size - elfheader? */ + /* set entry point and boot image size skipping over elf header */ + *entry = cpu_to_le32(0x400+65536); *length = cpu_to_le32(info.st_size+0x400); - /* - * Writes the "boot record", which contains the partition table, to the - * diskette, followed by the dummy PC boot block and load image descriptor - * block. It returns the number of bytes it has written to the load - * image. - * - * The boot record is the first block of the diskette and identifies the - * "PReP" partition. The "PReP" partition contains the "load image" starting - * at offset zero within the partition. The first block of the load image is - * a dummy PC boot block. The second block is the "load image descriptor" - * which contains the size of the load image and the entry point into the - * image. The actual boot image starts at offset 1024 bytes (third sector) - * in the partition. - */ - /* sets magic number for msdos partition (used by linux) */ block[510] = 0x55; block[511] = 0xAA; @@ -220,7 +204,7 @@ /* This has to be 0 on the PowerStack? */ pe->beginning_sector = cpu_to_le32(0); #endif -/*pe->number_of_sectors = cpu_to_le32(2*18*80-1);*/ + pe->number_of_sectors = cpu_to_le32(2*18*80-1); write( out, block, sizeof(block) ); write( out, entry, sizeof(*entry) ); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile --- v2.1.50/linux/arch/ppc/coffboot/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/Makefile Sat Aug 16 09:51:08 1997 @@ -0,0 +1,50 @@ +# Makefile for making XCOFF bootable images for booting on PowerMacs +# using Open Firmware. +# +# Paul Mackerras January 1997 + +# PowerPC (cross) tools +ifneq ($(shell uname -m),ppc) +CROSS_COMPILE =powerpc-eabi- +endif + +HOSTCC = gcc +HOSTCFLAGS = -O -I$(TOPDIR)/include + +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +CFLAGS = -O -fno-builtin -I$(TOPDIR)/include +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment \ + --add-section=image=zImage +LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic +GZIP = gzip -9 + +OBJS = crt0.o start.o main.o misc.o string.o zlib.o +LIBS = $(TOPDIR)/lib/lib.a + +vmlinux.coff: coffboot hack-coff zImage + $(OBJCOPY) $(OBJCOPY_ARGS) coffboot $@ + ./hack-coff $@ + +vmlinux.coff.initrd: coffboot hack-coff zImage ramdisk.image.gz + $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz \ + coffboot $@ + ./hack-coff $@ + +coffboot: $(OBJS) ld.script + $(LD) -o coffboot $(LD_ARGS) $(OBJS) $(LIBS) + +zImage: $(TOPDIR)/vmlinux elfextract + ./elfextract $(TOPDIR)/vmlinux | $(GZIP) >zImage + +hack-coff: hack-coff.c + $(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c + +elfextract: elfextract.c + $(HOSTCC) $(HOSTCFLAGS) -o elfextract elfextract.c + +clean: + rm -f elfextract hack-coff coffboot zImage vmlinux.coff + +fastdep: diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/crt0.S linux/arch/ppc/coffboot/crt0.S --- v2.1.50/linux/arch/ppc/coffboot/crt0.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/crt0.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,24 @@ +/* + * 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. + */ + .text + .globl _start +_start: + .long __start,0,0 + + .globl __start +__start: + lis 9,_start@h + lis 8,_etext@ha + addi 8,8,_etext@l +1: dcbf 0,9 + icbi 0,9 + addi 9,9,0x20 + cmplwi 0,9,8 + blt 1b + b start diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/elfextract.c linux/arch/ppc/coffboot/elfextract.c --- v2.1.50/linux/arch/ppc/coffboot/elfextract.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/elfextract.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,98 @@ +/* + * Extract the loadable program segment from an elf file. + * + * Copyright 1996 Paul Mackerras. + * + * 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 + +FILE *fi, *fo; +char *ni, *no; +char buf[65536]; + +void +rd(void *buf, int len) +{ + int nr; + + nr = fread(buf, 1, len, fi); + if (nr == len) + return; + if (ferror(fi)) + fprintf(stderr, "%s: read error\n", ni); + else + fprintf(stderr, "%s: short file\n", ni); + exit(1); +} + +main(int ac, char **av) +{ + unsigned nb, len; + Elf32_Ehdr eh; + Elf32_Phdr ph; + + if (ac > 3 || ac > 1 && av[1][0] == '-') { + fprintf(stderr, "Usage: %s [elf-file [image-file]]\n", av[0]); + exit(0); + } + + fi = stdin; + ni = "(stdin)"; + fo = stdout; + no = "(stdout)"; + + if (ac > 1) { + ni = av[1]; + fi = fopen(ni, "rb"); + if (fi == NULL) { + perror(ni); + exit(1); + } + } + + rd(&eh, sizeof(eh)); + if (eh.e_ident[EI_MAG0] != ELFMAG0 + || eh.e_ident[EI_MAG1] != ELFMAG1 + || eh.e_ident[EI_MAG2] != ELFMAG2 + || eh.e_ident[EI_MAG3] != ELFMAG3) { + fprintf(stderr, "%s: not an ELF file\n", ni); + exit(1); + } + + fseek(fi, eh.e_phoff + (eh.e_phnum - 1) * sizeof(ph), 0); + rd(&ph, sizeof(ph)); + if (ph.p_type != PT_LOAD) { + fprintf(stderr, "%s: doesn't have a loadable segment\n", ni); + exit(1); + } + + if (ac > 2) { + no = av[2]; + fo = fopen(no, "wb"); + if (fo == NULL) { + perror(no); + exit(1); + } + } + + fseek(fi, ph.p_offset, 0); + for (len = ph.p_filesz; len != 0; len -= nb) { + nb = len; + if (nb > sizeof(buf)) + nb = sizeof(buf); + rd(buf, nb); + if (fwrite(buf, 1, nb, fo) != nb) { + fprintf(stderr, "%s: write error\n", no); + exit(1); + } + } + + fclose(fo); + fclose(fi); + exit(0); +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/hack-coff.c linux/arch/ppc/coffboot/hack-coff.c --- v2.1.50/linux/arch/ppc/coffboot/hack-coff.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/hack-coff.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,79 @@ +/* + * hack-coff.c - hack the header of an xcoff file to fill in + * a few fields needed by the Open Firmware xcoff loader on + * Power Macs but not initialized by objcopy. + * + * 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. + */ +#include +#include "rs6000.h" + +#define AOUT_MAGIC 0x010b + +#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ + + ((unsigned char *)(x))[1]) +#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ + ((unsigned char *)(x))[1] = (v) & 0xff) +#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ + + (((unsigned char *)(x))[1] << 16) \ + + (((unsigned char *)(x))[2] << 8) \ + + ((unsigned char *)(x))[3]) + +main(int ac, char **av) +{ + int fd; + int i, nsect; + int aoutsz; + struct external_filehdr fhdr; + AOUTHDR aout; + struct external_scnhdr shdr; + + if (ac != 2) { + fprintf(stderr, "Usage: hack-coff coff-file\n"); + exit(1); + } + if ((fd = open(av[1], 2)) == -1) { + perror(av[2]); + exit(1); + } + if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) + goto readerr; + i = get_16be(fhdr.f_magic); + if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { + fprintf(stderr, "%s: not an xcoff file\n", av[1]); + exit(1); + } + aoutsz = get_16be(fhdr.f_opthdr); + if (read(fd, &aout, aoutsz) != aoutsz) + goto readerr; + nsect = get_16be(fhdr.f_nscns); + for (i = 0; i < nsect; ++i) { + if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) + goto readerr; + if (strcmp(shdr.s_name, ".text") == 0) { + put_16be(aout.o_snentry, i+1); + put_16be(aout.o_sntext, i+1); + } else if (strcmp(shdr.s_name, ".data") == 0) { + put_16be(aout.o_sndata, i+1); + } else if (strcmp(shdr.s_name, ".bss") == 0) { + put_16be(aout.o_snbss, i+1); + } + } + put_16be(aout.magic, AOUT_MAGIC); + if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 + || write(fd, &aout, aoutsz) != aoutsz) { + fprintf(stderr, "%s: write error\n", av[1]); + exit(1); + } + close(fd); + exit(0); + +readerr: + fprintf(stderr, "%s: read error or file too short\n", av[1]); + exit(1); +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/ld.script linux/arch/ppc/coffboot/ld.script --- v2.1.50/linux/arch/ppc/coffboot/ld.script Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/ld.script Sat Aug 16 09:51:08 1997 @@ -0,0 +1,68 @@ +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0 + .plt : { *(.plt) } + .text : + { + *(.text) + *(.rodata) + *(.rodata1) + *(.got1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + _etext = .; + PROVIDE (etext = .); + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.got.plt) *(.got) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/main.c linux/arch/ppc/coffboot/main.c --- v2.1.50/linux/arch/ppc/coffboot/main.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/main.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,185 @@ +/* + * 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. + */ +#include "nonstdio.h" +#include "rs6000.h" +#include "zlib.h" + +extern void *finddevice(const char *); +extern int getprop(void *, const char *, void *, int); +void gunzip(void *, int, unsigned char *, int *); + +#define get_16be(x) (*(unsigned short *)(x)) +#define get_32be(x) (*(unsigned *)(x)) + +#define RAM_START 0xc0000000 +#define RAM_END 0xc0800000 /* only 8M mapped with BATs */ + +#define RAM_FREE 0xc0540000 /* after image of coffboot */ + +char *avail_ram; +char *end_avail; + +coffboot(int a1, int a2, void *prom) +{ + void *options; + unsigned loadbase; + struct external_filehdr *eh; + struct external_scnhdr *sp; + struct external_scnhdr *isect, *rsect; + int ns, oh, i; + unsigned sa, len; + void *dst; + unsigned char *im; + unsigned initrd_start, initrd_size; + + printf("coffboot starting\n"); + options = finddevice("/options"); + if (options == (void *) -1) + exit(); + if (getprop(options, "load-base", &loadbase, sizeof(loadbase)) + != sizeof(loadbase)) { + printf("error getting load-base\n"); + exit(); + } + setup_bats(); + + eh = (struct external_filehdr *) loadbase; + ns = get_16be(eh->f_nscns); + oh = get_16be(eh->f_opthdr); + + sp = (struct external_scnhdr *) (loadbase + sizeof(struct external_filehdr) + oh); + isect = rsect = NULL; + for (i = 0; i < ns; ++i, ++sp) { + if (strcmp(sp->s_name, "image") == 0) + isect = sp; + else if (strcmp(sp->s_name, "initrd") == 0) + rsect = sp; + } + if (isect == NULL) { + printf("image section not found\n"); + exit(); + } + + if (rsect != NULL && (initrd_size = get_32be(rsect->s_size)) != 0) { + initrd_start = (RAM_END - initrd_size) & ~0xFFF; + a1 = initrd_start; + a2 = initrd_size; + printf("initial ramdisk at %x (%u bytes)\n", + initrd_start, initrd_size); + memcpy((char *) initrd_start, + (char *) (loadbase + get_32be(rsect->s_scnptr)), + initrd_size); + end_avail = (char *) initrd_start; + } else { + end_avail = (char *) RAM_END; + } + + im = (unsigned char *)(loadbase + get_32be(isect->s_scnptr)); + len = get_32be(isect->s_size); + dst = (void *) RAM_START; + + if (im[0] == 0x1f && im[1] == 0x8b) { + void *cp = (void *) RAM_FREE; + avail_ram = (void *) (RAM_FREE + ((len + 7) & -8)); + memcpy(cp, im, len); + printf("gunzipping... "); + gunzip(dst, 0x400000, cp, &len); + printf("done\n"); + + } else { + memmove(dst, im, len); + } + + flush_cache(dst, len); + + sa = *(unsigned *)dst + RAM_START; + printf("start address = 0x%x\n", sa); + +#if 0 + pause(); +#endif + (*(void (*)())sa)(a1, a2, prom); + + printf("returned?\n"); + + pause(); +} + +void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p = avail_ram; + + size *= items; + size = (size + 7) & -8; + avail_ram += size; + if (avail_ram > end_avail) { + printf("oops... out of memory\n"); + pause(); + } + return p; +} + +void zfree(void *x, void *addr, unsigned nb) +{ +} + +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +#define DEFLATED 8 + +void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + printf("bad gzipped data\n"); + exit(); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + printf("gunzip: ran out of data in header\n"); + exit(); + } + + s.zalloc = zalloc; + s.zfree = zfree; + r = inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf("inflateInit2 returned %d\n", r); + exit(); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + printf("inflate returned %d\n", r); + exit(); + } + *lenp = s.next_out - (unsigned char *) dst; + inflateEnd(&s); +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/misc.S linux/arch/ppc/coffboot/misc.S --- v2.1.50/linux/arch/ppc/coffboot/misc.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/misc.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,50 @@ +/* + * 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. + */ + .text + +/* + * Use the BAT0 registers to map the 1st 8MB of RAM to 0xc0000000. + */ + .globl setup_bats +setup_bats: + mfpvr 3 + rlwinm 3,3,16,16,31 /* r3 = 1 for 601, 4 for 604 */ + cmpi 0,3,1 + lis 4,0xc000 + bne 4f + ori 4,4,4 /* set up BAT registers for 601 */ + li 5,0x7f + b 5f +4: ori 4,4,0xff /* set up BAT registers for 604 */ + li 5,2 + mtdbatu 0,4 + mtdbatl 0,5 +5: mtibatu 0,4 + mtibatl 0,5 + isync + blr + +/* + * Flush the dcache and invalidate the icache for a range of addresses. + * + * flush_cache(addr, len) + */ + .global flush_cache +flush_cache: + addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ + rlwinm. 4,4,27,5,31 + mtctr 4 + beqlr +1: dcbf 0,3 + icbi 0,3 + addi 3,3,0x20 + bdnz 1b + sync + isync + blr diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/nonstdio.h linux/arch/ppc/coffboot/nonstdio.h --- v2.1.50/linux/arch/ppc/coffboot/nonstdio.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/nonstdio.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,18 @@ +/* + * 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.50/linux/arch/ppc/coffboot/rs6000.h linux/arch/ppc/coffboot/rs6000.h --- v2.1.50/linux/arch/ppc/coffboot/rs6000.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/rs6000.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,243 @@ +/* IBM RS/6000 "XCOFF" file definitions for BFD. + Copyright (C) 1990, 1991 Free Software Foundation, Inc. + FIXME: Can someone provide a transliteration of this name into ASCII? + Using the following chars caused a compiler warning on HIUX (so I replaced + them with octal escapes), and isn't useful without an understanding of what + character set it is. + Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM + and John Gilmore of Cygnus Support. */ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; + + /* IBM RS/6000 */ +#define U802WRMAGIC 0730 /* writeable text segments **chh** */ +#define U802ROMAGIC 0735 /* readonly sharable text segments */ +#define U802TOCMAGIC 0737 /* readonly text segments and TOC */ + +#define BADMAG(x) \ + ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ + (x).f_magic != U802TOCMAGIC) + +#define FILHDR struct external_filehdr +#define FILHSZ 20 + + +/********************** AOUT "OPTIONAL HEADER" **********************/ + + +typedef struct +{ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ + unsigned char dsize[4]; /* initialized data " " */ + unsigned char bsize[4]; /* uninitialized data " " */ + unsigned char entry[4]; /* entry pt. */ + unsigned char text_start[4]; /* base of text used for this file */ + unsigned char data_start[4]; /* base of data used for this file */ + unsigned char o_toc[4]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ + unsigned char o_cputype[2]; /* cpu type */ + unsigned char o_maxstack[4]; /* max stack size (??) */ + unsigned char o_maxdata[4]; /* max data size (??) */ + unsigned char o_resv2[12]; /* reserved */ +} +AOUTHDR; + +#define AOUTSZ 72 +#define SMALL_AOUTSZ (28) +#define AOUTHDRSZ 72 + +#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ +#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ +#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ + + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries*/ + char s_flags[4]; /* flags */ +}; + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _PAD ".pad" +#define _LOADER ".loader" + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* XCOFF uses a special .loader section with type STYP_LOADER. */ +#define STYP_LOADER 0x1000 + +/* XCOFF uses a special .debug section with type STYP_DEBUG. */ +#define STYP_DEBUG 0x2000 + +/* XCOFF handles line number or relocation overflow by creating + another section header with STYP_OVRFLO set. */ +#define STYP_OVRFLO 0x8000 + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + char l_lnno[2]; /* line number */ +}; + + +#define LINENO struct external_lineno +#define LINESZ 6 + + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + char e_value[4]; + char e_scnum[2]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +}; + + + +#define N_BTMASK (017) +#define N_TMASK (060) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + + +union external_auxent { + struct { + char x_tagndx[4]; /* str, un, or enum tag indx */ + union { + struct { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + char x_fsize[4]; /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + char x_tvndx[2]; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + } x_file; + + struct { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ + } x_scn; + + struct { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + struct { + unsigned char x_scnlen[4]; + unsigned char x_parmhash[4]; + unsigned char x_snhash[2]; + unsigned char x_smtyp[1]; + unsigned char x_smclas[1]; + unsigned char x_stab[4]; + unsigned char x_snstab[2]; + } x_csect; + +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 +#define AUXENT union external_auxent +#define AUXESZ 18 +#define DBXMASK 0x80 /* for dbx storage mask */ +#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) + + + +/********************** RELOCATION DIRECTIVES **********************/ + + +struct external_reloc { + char r_vaddr[4]; + char r_symndx[4]; + char r_size[1]; + char r_type[1]; +}; + + +#define RELOC struct external_reloc +#define RELSZ 10 + +#define DEFAULT_DATA_SECTION_ALIGNMENT 4 +#define DEFAULT_BSS_SECTION_ALIGNMENT 4 +#define DEFAULT_TEXT_SECTION_ALIGNMENT 4 +/* For new sections we havn't heard of before */ +#define DEFAULT_SECTION_ALIGNMENT 4 diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/start.c linux/arch/ppc/coffboot/start.c --- v2.1.50/linux/arch/ppc/coffboot/start.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/start.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,280 @@ +/* + * 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. + */ +#include + +int (*prom)(); + +void *chosen_handle; +void *stdin; +void *stdout; +void *stderr; + +void exit(void); +void *finddevice(const char *name); +int getprop(void *phandle, const char *name, void *buf, int buflen); + +void +start(int a1, int a2, void *promptr) +{ + prom = (int (*)()) promptr; + chosen_handle = finddevice("/chosen"); + if (chosen_handle == (void *) -1) + exit(); + if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) + exit(); + stderr = stdout; + if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) + exit(); + + coffboot(a1, a2, promptr); + for (;;) + exit(); +} + +int +write(void *handle, void *ptr, int nb) +{ + struct prom_args { + char *service; + int nargs; + int nret; + void *ihandle; + void *addr; + int len; + int actual; + } args; + + args.service = "write"; + args.nargs = 3; + args.nret = 1; + args.ihandle = handle; + args.addr = ptr; + args.len = nb; + args.actual = -1; + (*prom)(&args); + return args.actual; +} + +int +read(void *handle, void *ptr, int nb) +{ + struct prom_args { + char *service; + int nargs; + int nret; + void *ihandle; + void *addr; + int len; + int actual; + } args; + + args.service = "read"; + args.nargs = 3; + args.nret = 1; + args.ihandle = handle; + args.addr = ptr; + args.len = nb; + args.actual = -1; + (*prom)(&args); + return args.actual; +} + +void +exit() +{ + struct prom_args { + char *service; + } args; + + for (;;) { + args.service = "exit"; + (*prom)(&args); + } +} + +void +pause() +{ + struct prom_args { + char *service; + } args; + + args.service = "enter"; + (*prom)(&args); +} + +void * +finddevice(const char *name) +{ + struct prom_args { + char *service; + int nargs; + int nret; + const char *devspec; + void *phandle; + } args; + + args.service = "finddevice"; + args.nargs = 1; + args.nret = 1; + args.devspec = name; + args.phandle = (void *) -1; + (*prom)(&args); + return args.phandle; +} + +int +getprop(void *phandle, const char *name, void *buf, int buflen) +{ + struct prom_args { + char *service; + int nargs; + int nret; + void *phandle; + const char *name; + void *buf; + int buflen; + int size; + } args; + + args.service = "getprop"; + args.nargs = 4; + args.nret = 1; + args.phandle = phandle; + args.name = name; + args.buf = buf; + args.buflen = buflen; + args.size = -1; + (*prom)(&args); + return args.size; +} + +int +putc(int c, void *f) +{ + char ch = c; + + if (c == '\n') + putc('\r', f); + return write(f, &ch, 1) == 1? c: -1; +} + +int +putchar(int c) +{ + return putc(c, stdout); +} + +int +fputs(char *str, void *f) +{ + int n = strlen(str); + + return write(f, str, n) == n? 0: -1; +} + +int +readchar() +{ + char ch; + + for (;;) { + switch (read(stdin, &ch, 1)) { + case 1: + return ch; + case -1: + printk("read(stdin) returned -1\r\n"); + return -1; + } + } +} + +static char line[256]; +static char *lineptr; +static int lineleft; + +int +getchar() +{ + int c; + + if (lineleft == 0) { + lineptr = line; + for (;;) { + c = readchar(); + if (c == -1 || c == 4) + break; + if (c == '\r' || c == '\n') { + *lineptr++ = '\n'; + putchar('\n'); + break; + } + switch (c) { + case 0177: + case '\b': + if (lineptr > line) { + putchar('\b'); + putchar(' '); + putchar('\b'); + --lineptr; + } + break; + case 'U' & 0x1F: + while (lineptr > line) { + putchar('\b'); + putchar(' '); + putchar('\b'); + --lineptr; + } + break; + default: + if (lineptr >= &line[sizeof(line) - 1]) + putchar('\a'); + else { + putchar(c); + *lineptr++ = c; + } + } + } + lineleft = lineptr - line; + lineptr = line; + } + if (lineleft == 0) + return -1; + --lineleft; + return *lineptr++; +} + +extern int vsprintf(char *buf, const char *fmt, va_list args); +static char sprint_buf[1024]; + +void +printk(char *fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vsprintf(sprint_buf, fmt, args); + va_end(args); + write(stdout, sprint_buf, n); +} + +int +printf(char *fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vsprintf(sprint_buf, fmt, args); + va_end(args); + write(stdout, sprint_buf, n); + return n; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/string.S linux/arch/ppc/coffboot/string.S --- v2.1.50/linux/arch/ppc/coffboot/string.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/string.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,206 @@ +/* + * String handling functions for PowerPC. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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. + */ +#define r0 0 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 + + .globl strcpy +strcpy: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r5) + bne 1b + blr + + .globl strncpy +strncpy: + cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r6) + bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ + blr + + .globl strcat +strcat: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r5) + cmpwi 0,r0,0 + bne 1b + addi r5,r5,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r5) + bne 1b + blr + + .globl strcmp +strcmp: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r3,1(r5) + cmpwi 1,r3,0 + lbzu r0,1(r4) + subf. r3,r0,r3 + beqlr 1 + beq 1b + blr + + .globl strlen +strlen: + addi r4,r3,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + bne 1b + subf r3,r3,r4 + blr + + .globl memset +memset: + rlwimi r4,r4,8,16,23 + rlwimi r4,r4,16,0,15 + addi r6,r3,-4 + cmplwi 0,r5,4 + blt 7f + stwu r4,4(r6) + beqlr + andi. r0,r6,3 + add r5,r0,r5 + subf r6,r0,r6 + rlwinm r0,r5,32-2,2,31 + mtctr r0 + bdz 6f +1: stwu r4,4(r6) + bdnz 1b +6: andi. r5,r5,3 +7: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r6,3 +8: stbu r4,1(r6) + bdnz 8b + blr + + .globl bcopy +bcopy: + mr r6,r3 + mr r3,r4 + mr r4,r6 + b memcpy + + .globl memmove +memmove: + cmplw 0,r3,r4 + bgt backwards_memcpy + /* fall through */ + + .globl memcpy +memcpy: + rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + addi r6,r3,-4 + addi r4,r4,-4 + 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) + lwzu r8,8(r4) + stw r7,4(r6) + stwu r8,8(r6) + bdnz 1b + andi. r5,r5,7 +2: cmplwi 0,r5,4 + blt 3f + lwzu r0,4(r4) + addi r5,r5,-4 + stwu r0,4(r6) +3: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r4,r4,3 + addi r6,r6,3 +4: lbzu r0,1(r4) + stbu r0,1(r6) + bdnz 4b + blr +5: subfic r0,r0,4 + mtctr r0 +6: lbz r7,4(r4) + addi r4,r4,1 + stb r7,4(r6) + addi r6,r6,1 + bdnz 6b + subf r5,r0,r5 + rlwinm. r7,r5,32-3,3,31 + beq 2b + mtctr r7 + b 1b + + .globl backwards_memcpy +backwards_memcpy: + rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + add r6,r3,r5 + add r4,r4,r5 + beq 2f + andi. r0,r6,3 + mtctr r7 + bne 5f +1: lwz r7,-4(r4) + lwzu r8,-8(r4) + stw r7,-4(r6) + stwu r8,-8(r6) + bdnz 1b + andi. r5,r5,7 +2: cmplwi 0,r5,4 + blt 3f + lwzu r0,-4(r4) + subi r5,r5,4 + stwu r0,-4(r6) +3: cmpwi 0,r5,0 + beqlr + mtctr r5 +4: lbzu r0,-1(r4) + stbu r0,-1(r6) + bdnz 4b + blr +5: mtctr r0 +6: lbzu r7,-1(r4) + stbu r7,-1(r6) + bdnz 6b + subf r5,r0,r5 + rlwinm. r7,r5,32-3,3,31 + beq 2b + mtctr r7 + b 1b + + .globl memcmp +memcmp: + cmpwi 0,r5,0 + blelr + mtctr r5 + addi r6,r3,-1 + addi r4,r4,-1 +1: lbzu r3,1(r6) + lbzu r0,1(r4) + subf. r3,r0,r3 + bdnzt 2,1b + blr diff -u --recursive --new-file v2.1.50/linux/arch/ppc/coffboot/zlib.c linux/arch/ppc/coffboot/zlib.c --- v2.1.50/linux/arch/ppc/coffboot/zlib.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/zlib.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,2143 @@ +/* + * 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/07/31 07:16:14 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.50/linux/arch/ppc/coffboot/zlib.h linux/arch/ppc/coffboot/zlib.h --- v2.1.50/linux/arch/ppc/coffboot/zlib.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/coffboot/zlib.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,432 @@ +/* $Id: zlib.h,v 1.1 1997/07/31 07:16:15 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< .depend - -dep: - $(CPP) -M *.S *.c > .depend - -modules: - -dummy: - -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/checks.c linux/arch/ppc/kernel/checks.c --- v2.1.50/linux/arch/ppc/kernel/checks.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/checks.c Sat Aug 16 09:51:08 1997 @@ -25,7 +25,7 @@ int main(void) { int ret = 0; - +#if 0 if ( sizeof(struct thread_struct) % 16 ) { printf("Thread struct is not modulo 16 bytes: " @@ -34,6 +34,7 @@ sizeof(struct thread_struct)%16); ret = -1; } +#endif if ( sizeof(struct pt_regs) % 16 ) { diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.1.50/linux/arch/ppc/kernel/head.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/head.S Sat Aug 16 09:51:08 1997 @@ -45,14 +45,13 @@ #define TOPHYS(x) (x - KERNELBASE) - /* this is a very kludgey way of loading up the BATs on the prep system. I'll kill this horrible macro and write something clean when I have a chance -- Cort */ #define LOAD_BATS(RA,RB) \ mfspr RA,PVR ; \ - srwi r5,r5,16 ; \ + srwi RA,RA,16 ; \ cmpi 0,RA,1 ; \ beq 199f ; \ /* load bats for 60x */ ; \ @@ -132,21 +131,10 @@ mtspr DBAT3L,RB ; \ 200: - - - .text .globl _stext _stext: -#ifdef CONFIG_PREP - . = 0x100 -_GLOBAL(HardReset) - b _start - -#endif /* CONFIG_PREP */ - -#ifdef CONFIG_PMAC /* * _start is defined this way because the XCOFF loader in the OpenFirmware * on the powermac expects the entry point to be a procedure descriptor. @@ -156,7 +144,7 @@ _start: .long TOPHYS(__start),0,0 -/* +/* PMAC * Enter here with the kernel text, data and bss loaded starting at * 0, running with virtual == physical mapping. * r5 points to the prom entry point (the client interface handler @@ -165,41 +153,81 @@ * pointer (r1) points to just below the end of the half-meg region * from 0x380000 - 0x400000, which is mapped in already. */ +/* 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 + * of the regs is: + * r3: ptr to residual data + * r4: initrd_start or if no initrd then 0 + * r5: initrd_end - unused if r4 is 0 + * r6: Start of command line string + * r7: End of command line string + * + * This just gets a minimal mmu environment setup so we can call + * start_here() to do the real work. + * -- Cort + */ + .globl __start __start: /* - * Use the first pair of BAT registers to map the 1st 8MB + * Use the first pair of BAT registers to map the 1st 16MB * of RAM to KERNELBASE. */ mfspr r9,PVR rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ cmpi 0,r9,1 - lis r7,KERNELBASE@h + lis r11,KERNELBASE@h bne 4f - ori r7,r7,4 /* set up BAT registers for 601 */ + 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 r7,r7,0xff /* set up BAT registers for 604 */ +4: ori r11,r11,0x1ff /* set up BAT registers for 604 */ li r8,2 - mtspr DBAT0U,r7 + mtspr DBAT0U,r11 mtspr DBAT0L,r8 -5: mtspr IBAT0U,r7 +5: mtspr IBAT0U,r11 mtspr IBAT0L,r8 isync +#if 0 /* * Now we have the 1st 8M of RAM mapped at KERNELBASE, so we can * refer to addresses of data items, procedures, etc. normally. */ - lis r7,start_here@ha /* jump up to our copy at KERNELBASE */ - addi r7,r7,start_here@l - mtlr r7 + lis r10,start_here@ha /* jump up to our copy at KERNELBASE */ + addi r10,r10,start_here@l + mtlr r10 blr -#endif /* CONFIG_PMAC */ - - +#endif +/* + * 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,start_here@h + ori r0,r0,start_here@l + 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 + * this, we leave this much untouched space on the stack on exception + * entry. + */ +#define STACK_UNDERHEAD 64 /* * Macros for storing registers into and loading registers from @@ -286,10 +314,8 @@ .long hdlr; \ .long int_return -#ifndef CONFIG_PREP /* System reset */ STD_EXCEPTION(0x100, Reset, UnknownException) -#endif /* ndef CONFIG_PREP */ /* Machine check */ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) @@ -319,7 +345,7 @@ /* Instruction access exception */ . = 0x400 -InstructionAccess: +InstructionAccess: EXCEPTION_PROLOG andis. r0,r23,0x4000 /* no pte found? */ beq 1f /* if so, try to put a PTE */ @@ -338,7 +364,7 @@ .long int_return /* External interrupt */ - STD_EXCEPTION(0x500, HardwareInterrupt, handle_IRQ) + STD_EXCEPTION(0x500, HardwareInterrupt, do_IRQ) /* Alignment exception */ . = 0x600 @@ -376,21 +402,7 @@ .long KernelFP .long int_return -/* Decrementer */ -#ifdef CONFIG_PREP -/* - ignored for now... */ -_ORG(0x0900) - mtspr SPRG0,r1 - lis r1,0x7FFF - ori r1,r1,0xFFFF - mtspr DEC,r1 - mfspr r1,SPRG0 - rfi -#endif /* CONFIG_PREP */ -#ifdef CONFIG_PMAC STD_EXCEPTION(0x900, Decrementer, timer_interrupt) -#endif /* CONFIG_PMAC */ - STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) @@ -596,11 +608,6 @@ andi. r23,r23,MSR_PR mfspr r23,SPRG3 /* if from user, fix up tss */ beq 2f -#ifdef CONFIG_PMAC - lwz r24,GPR1(r21) - stw r22,LAST_PC(r23) - stw r24,USER_STACK(r23) -#endif /* CONFIG_PMAC */ addi r24,r1,STACK_FRAME_OVERHEAD stw r24,PT_REGS(r23) 2: addi r2,r23,-TSS /* set r2 to current */ @@ -630,7 +637,7 @@ REST_32FPRS(0, r5) /* use last_task_used_math instead of fpu_tss */ - lis r3,last_task_used_math@h/*a*/ + lis r3,last_task_used_math@ha addis r3,r3,-KERNELBASE@h subi r4,r5,TSS addis r4,r4,KERNELBASE@h @@ -654,7 +661,7 @@ REST_GPR(20, r21) REST_2GPRS(22, r21) lwz r21,GPR21(r21) - SYNC + SYNC rfi /* @@ -682,14 +689,15 @@ .globl hash_page hash_page: /* Get PTE (linux-style) and check access */ - lwz r5,PG_TABLES(r5) /* task's page tables */ - lis r2,-KERNELBASE@h - add r5,r5,r2 /* convert to phys addr */ + lwz r5,MM-TSS(r5) + addis r5,r5,-KERNELBASE@h /* get physical current->mm */ + lwz r5,PGD(r5) /* get current->mm->pgd */ + addis r5,r5,-KERNELBASE@h /* convert to phys addr */ rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */ lwz r5,0(r5) /* get pmd entry */ rlwinm. r5,r5,0,0,19 /* extract address of pte page */ beqlr- /* return if no mapping */ - add r2,r5,r2 + addis r2,r5,-KERNELBASE@h rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ lwz r6,0(r2) /* get linux-style pte */ ori r4,r4,1 /* set _PAGE_PRESENT bit in access */ @@ -819,58 +827,64 @@ rlwinm r9,r9,16,16,31 cmpi 0,r9,1 beq 4f /* not needed for 601 */ - mfspr r7,HID0 - andi. r0,r7,HID0_DCE - ori r7,r7,HID0_ICE|HID0_DCE - ori r8,r7,HID0_ICFI + 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: sync +3: + /* I haven't tested this yet so it's off now - Cort */ + /* 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,r7 /* enable caches */ + mtspr HID0,r11 /* enable caches */ sync isync cmpi 0,r9,4 /* check for 604 */ cmpi 1,r9,9 /* or 604e */ cror 2,2,6 bne 4f - ori r7,r7,HID0_SIED|HID0_BHTE /* for 604[e], enable */ - mtspr HID0,r7 /* superscalar exec & br history tbl */ + ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */ + mtspr HID0,r11 /* superscalar exec & br history tbl */ 4: /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l /* ptr to phys current tss */ - addis r3,r2,-KERNELBASE@h - addi r3,r3,TSS /* init task's TSS */ - mtspr SPRG3,r3 + addis r11,r2,-KERNELBASE@h + addi r11,r11,TSS /* init task's TSS */ + mtspr SPRG3,r11 /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) /* Clear out the BSS */ - lis r7,_end@ha - addi r7,r7,_end@l + lis r11,_end@ha + addi r11,r11,_end@l lis r8,__bss_start@ha addi r8,r8,__bss_start@l - subf r7,r8,r7 - addi r7,r7,3 - rlwinm. r7,r7,30,2,31 + subf r11,r8,r11 + addi r11,r11,3 + rlwinm. r11,r11,30,2,31 beq 2f addi r8,r8,-4 - mtctr r7 + mtctr r11 li r0,0 3: stwu r0,4(r8) bdnz 3b 2: /* - * Initialize the prom stuff (powermacs only) and the MMU. + * Initialize the prom stuff and the MMU. */ -#ifdef CONFIG_PMAC + bl identify_machine bl prom_init -#endif /* CONFIG_PMAC */ bl MMU_init /* @@ -889,11 +903,6 @@ rfi /* Load up the kernel context */ 2: -#ifdef CONFIG_PREP - /* reload the bats now that MMU_init() has setup them up -- Cort */ - LOAD_BATS(r3,r0) -#endif - SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ mtspr SDR1,r6 @@ -905,8 +914,19 @@ addi r3,r3,1 /* increment VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b -#ifdef CONFIG_PMAC - li r0,0 /* zot the BATs */ + + lis r3,_machine@ha + addis r3,r3,-KERNELBASE@h + lwz r0,_machine@l(r3) + cmpi 0,r0,_MACH_Pmac + beq 99f + +/* on prep reload the bats now that MMU_init() has setup them up -- Cort */ + LOAD_BATS(r3,r14) + b 100f + +/* on pmac clear the bats out */ +99: li r0,0 /* zot the BATs */ #if 1 mtspr IBAT0U,r0 mtspr IBAT0L,r0 @@ -925,7 +945,7 @@ mtspr IBAT3L,r0 mtspr DBAT3U,r0 mtspr DBAT3L,r0 -#endif +100: /* Now turn on the MMU for real! */ li r4,MSR_KERNEL lis r3,start_kernel@h @@ -934,61 +954,6 @@ mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ -#ifdef CONFIG_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 - * of the regs is: - * R3: End of image - * R4: Start of image - 0x400 - * R11: Start of command line string - * R12: End of command line string - * - * This just gets a minimal mmu environment setup so we can call - * start_here() to do the real work. - * -- Cort - */ - .globl __start -__start: - .globl _start -_start: - lis r7,0xF000 /* To mask upper 4 bits */ -/* save pointer to residual data */ - lis r1,resptr@h - ori r1,r1,resptr@l - addis r1,r1,-KERNELBASE@h - stw r3,0(r1) -/* save argument string */ - li r0,0 /* Null terminate string */ - stb r0,0(r12) - lis r1,cmd_line@h - ori r1,r1,cmd_line@l - addis r1,r1,-KERNELBASE@h - subi r1,r1,1 - subi r11,r11,1 -00: lbzu r0,1(r11) - cmpi 0,r0,0 - stbu r0,1(r1) - bne 00b -/* setup the msr with sane values */ - li r0,MSR_ - mtmsr r0 -/* turn on the mmu with bats covering kernel enough to get started */ - LOAD_BATS(r3,r0) - mfmsr r3 - ori r3,r3,MSR_DR|MSR_IR - mtspr SRR1,r3 - lis r3,10f@h - ori r3,r3,10f@l - mtspr SRR0,r3 - SYNC - rfi /* enables MMU */ -10: lis r7,start_here@ha /* jump up to our copy at KERNELBASE */ - addi r7,r7,start_here@l - mtlr r7 - blr -#endif /* CONFIG_PREP */ - /* * FP unavailable trap from kernel - print a message, but let * the task use FP in the kernel until it returns to user mode. @@ -1022,31 +987,23 @@ giveup_fpu: li r6,0 1: - addis r3,r6,last_task_used_math@h/*a*/ + addis r3,r6,last_task_used_math@ha lwz r4,last_task_used_math@l(r3) -#if 0 - addis r3,r6,fpu_tss@ha - lwz r4,fpu_tss@l(r3) -#endif mfmsr r5 ori r5,r5,MSR_FP SYNC mtmsr r5 /* enable use of fpu now */ SYNC cmpi 0,r4,0 + beqlr- /* if no previous owner, done */ add r4,r4,r6 - beqlr /* if no previous owner, done */ addi r4,r4,TSS /* want TSS of last_task_used_math */ li r5,0 stw r5,last_task_used_math@l(r3) -#if 0 - stw r5,fpu_tss@l(r3) -#endif SAVE_32FPRS(0, r4) mffs fr0 stfd fr0,TSS_FPSCR-4(r4) lwz r5,PT_REGS(r4) - lwz r5,PT_REGS(r4) add r5,r5,r6 lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5) li r4,MSR_FP @@ -1268,7 +1225,7 @@ cmpi 0,r4,0 beq+ 1f addi r3,r1,STACK_FRAME_OVERHEAD - bl handle_IRQ + bl do_IRQ b 3b 1: lis r4,bh_mask@ha lwz r4,bh_mask@l(r4) @@ -1341,7 +1298,7 @@ li r0,0x0fac stw r0,TRAP(r1) addi r3,r1,STACK_FRAME_OVERHEAD - bl handle_IRQ + bl do_IRQ addi r1,r1,INT_FRAME_SIZE+STACK_UNDERHEAD lwz r0,4(r1) mtlr r0 @@ -1384,11 +1341,11 @@ * and invalidate the corresponding instruction cache blocks. * This is a no-op on the 601. * - * store_cache_range(unsigned long start, unsigned long stop) + * flush_icache_range(unsigned long start, unsigned long stop) */ CACHE_LINE_SIZE = 32 LG_CACHE_LINE_SIZE = 5 -_GLOBAL(store_cache_range) +_GLOBAL(flush_icache_range) mfspr r5,PVR rlwinm r5,r5,16,16,31 cmpi 0,r5,1 @@ -1521,7 +1478,6 @@ _GLOBAL(__main) blr -#ifdef CONFIG_PMAC /* * These exception handlers are used when we have called a prom * routine after we have taken over the exception vectors and MMU. @@ -1716,7 +1672,6 @@ lwz r31,28(r1) lwz r1,0(r1) blr -#endif /* * We put a few things here that have to be page-aligned. @@ -1726,7 +1681,6 @@ .data .globl sdata sdata: - .space 2*4096 .globl empty_zero_page empty_zero_page: .space 4096 @@ -1735,7 +1689,6 @@ swapper_pg_dir: .space 4096 -#ifdef CONFIG_PREP /* * This space gets a copy of optional info passed to us by the bootstrap * Used to pass parameters into the kernel like root=/dev/sda1, etc. @@ -1743,5 +1696,4 @@ .globl cmd_line cmd_line: .space 512 -#endif /* CONFIG_PREP */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.1.50/linux/arch/ppc/kernel/idle.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/idle.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,278 @@ +/* + * $Id: idle.c,v 1.3 1997/08/10 04:49:08 davem Exp $ + * + * Idle daemon for PowerPC. Idle daemon will handle any action + * that needs to be taken when the system becomes idle. + * + * 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. + */ +#define __KERNEL_SYSCALLS__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int zero_paged(void *unused); +int power_saved(void *unused); + +asmlinkage int sys_idle(void) +{ + int ret = -EPERM; + + if (current->pid != 0) + goto out; + + /* + * want one per cpu since it would be nice to have all + * processors who aren't doing anything + * zero-ing pages since this daemon is lock-free + * -- Cort + */ + kernel_thread(zero_paged, NULL, 0); + /* no powersaving modes on 601 */ + /*if( (_get_PVR()>>16) != 1 ) + kernel_thread(power_saved, NULL, 0);*/ + + /* endless loop with no priority at all */ + current->priority = -100; + current->counter = -100; + for (;;) + { + schedule(); + } + ret = 0; +out: + return ret; +} + +/* + * vars for idle task zero'ing out pages + */ +unsigned long zero_list = 0; /* head linked list of pre-zero'd pages */ +unsigned long bytecount = 0; /* pointer into the currently being zero'd page */ +unsigned long zerocount = 0; /* # currently pre-zero'd pages */ +unsigned long zerototal = 0; /* # pages zero'd over time -- for ooh's and ahhh's */ +unsigned long pageptr = 0; /* current page being zero'd */ +unsigned long zeropage_hits = 0;/* # zero'd pages request that we've done */ +unsigned long zeropage_calls = 0;/* # zero'd pages request that've been made */ +static struct wait_queue * page_zerod_wait = NULL; +#define PAGE_THRESHOLD 96 /* how many pages to keep pre-zero'd */ + +/* + * Returns a pre-zero'd page from the list otherwise returns + * NULL. + */ +unsigned long get_prezerod_page(void) +{ + unsigned long page; + + atomic_inc((atomic_t *)&zeropage_calls); + if ( zero_list ) + { + /* atomically remove this page from the list */ + asm ( "101:lwarx %1,0,%2\n" /* reserve zero_list */ + " lwz %0,0(%1)\n" /* get next -- new zero_list */ + " stwcx. %0,0,%2\n" /* update zero_list */ + " bne- 101b\n" /* if lost reservation try again */ + : "=&r" (zero_list), "=&r" (page) + : "r" (&zero_list) + : "cc" ); + /* we can update zerocount after the fact since it is not + * used for anything but control of a loop which doesn't + * matter since it won't effect anything if it zero's one + * less page -- Cort + */ + atomic_inc((atomic_t *)&zeropage_hits); + atomic_dec((atomic_t *)&zerocount); + wake_up(&page_zerod_wait); + resched_force(); + + /* zero out the pointer to next in the page */ + *(unsigned long *)page = 0; + return page; + } + return 0; +} + +/* + * Experimental stuff to zero out pages in the idle task + * to speed up get_free_pages() -- Cort + * Zero's out pages until we need to resched or + * we've reached the limit of zero'd pages. + */ + +int zero_paged(void *unused) +{ + extern pte_t *get_pte( struct mm_struct *mm, unsigned long address ); + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + + sprintf(current->comm, "zero_paged (idle)"); + current->blocked = ~0UL; + + printk("Started zero_paged\n"); + + __sti(); + while ( 1 ) + { + /* don't want to be pre-empted by swapper or power_saved */ + current->priority = -98; + current->counter = -98; + /* we don't want to run until we have something to do */ + while ( zerocount >= PAGE_THRESHOLD ) + sleep_on(&page_zerod_wait); + /* + * Mark a page as reserved so we can mess with it + * If we're interrupted we keep this page and our place in it + * since we validly hold it and it's reserved for us. + */ + pageptr = __get_free_pages(GFP_ATOMIC, 0, 0 ); + if ( !pageptr ) + { + printk("!pageptr in zero_paged\n"); + goto retry; + } + + if ( resched_needed() ) + schedule(); + + /* + * Make the page no cache so we don't blow our cache with 0's + */ + dir = pgd_offset( init_task.mm, pageptr ); + if (dir) + { + pmd = pmd_offset(dir, pageptr & PAGE_MASK); + if (pmd && pmd_present(*pmd)) + { + pte = pte_offset(pmd, pageptr & PAGE_MASK); + if (pte && pte_present(*pte)) + { + pte_uncache(*pte); + flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); + } + } + } + + /* + * Important here to not take time away from real processes. + */ + for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 ) + { + if ( resched_needed() ) + schedule(); + *(unsigned long *)(bytecount + pageptr) = 0; + } + + /* + * If we finished zero-ing out a page add this page to + * the zero_list atomically -- we can't use + * down/up since we can't sleep in idle. + * Disabling interrupts is also a bad idea since we would + * steal time away from real processes. + * We can also have several zero_paged's running + * on different processors so we can't interfere with them. + * So we update the list atomically without locking it. + * -- Cort + */ + /* turn cache on for this page */ + pte_cache(*pte); + flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); + + /* atomically add this page to the list */ + asm ( "101:lwarx %0,0,%1\n" /* reserve zero_list */ + " stw %0,0(%2)\n" /* update *pageptr */ +#ifdef __SMP__ + " sync\n" /* let store settle */ +#endif + " mr %0,%2\n" /* update zero_list in reg */ + " stwcx. %2,0,%1\n" /* update zero_list in mem */ + " bne- 101b\n" /* if lost reservation try again */ + : "=&r" (zero_list) + : "r" (&zero_list), "r" (pageptr) + : "cc" ); + /* + * This variable is used in the above loop and nowhere + * else so the worst that could happen is we would + * zero out one more or one less page than we want + * per processor on the machine. This is because + * we could add our page to the list but not have + * zerocount updated yet when another processor + * reads it. -- Cort + */ + atomic_inc((atomic_t *)&zerocount); + atomic_inc((atomic_t *)&zerototal); +retry: + schedule(); + } +} + +int power_saved(void *unused) +{ + unsigned long msr, hid0; + sprintf(current->comm, "power_saved (idle)"); + current->blocked = ~0UL; + + printk("Power saving daemon started\n"); + + __sti(); + while (1) + { + /* don't want to be pre-empted by swapper */ + current->priority = -99; + current->counter = -99; + /* go ahead and wakeup page_zerod() */ + wake_up(&page_zerod_wait); + schedule(); + asm volatile( + /* clear powersaving modes and set nap mode */ + "mfspr %3,1008 \n\t" + "andc %3,%3,%4 \n\t" + "or %3,%3,%5 \n\t" + "mtspr 1008,%3 \n\t" + /* enter the mode */ + "mfmsr %0 \n\t" + "oris %0,%0,%2 \n\t" + "sync \n\t" + "mtmsr %0 \n\t" + "isync \n\t" + : "=&r" (msr) + : "0" (msr), "i" (MSR_POW>>16), + "r" (hid0), + "r" (HID0_DOZE|HID0_NAP|HID0_SLEEP), + "r" (HID0_NAP)); + /* + * The ibm carolina spec says that the eagle memory + * controller will detect the need for a snoop + * and wake up the processor so we don't need to + * check for cache operations that need to be + * snooped. The ppc book says the run signal + * must be asserted while napping for this though. + * + * Paul, what do you know about the pmac here? + * -- Cort + */ + schedule(); + } +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.1.50/linux/arch/ppc/kernel/irq.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/irq.c Sat Aug 16 09:51:08 1997 @@ -1,13 +1,13 @@ /* * arch/ppc/kernel/irq.c * - * Power Macintosh version - * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) - * * Derived from arch/i386/kernel/irq.c * Copyright (C) 1992 Linus Torvalds * Adapted from arch/i386 by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu) + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * Updated and modified by Cort Dougan (cort@cs.nmt.edu) + * Adapted for Power Macintosh by Paul Mackerras + * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) * * This file contains the code used by various IRQ handling routines: * asking for different IRQ's should be done through these routines @@ -15,11 +15,7 @@ * shouldn't result in any weird surprises, and installing new handlers * should be easier. */ - -/* - * IRQ's are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ + #include #include @@ -30,20 +26,15 @@ #include #include #include +#include +#include #include #include #include #include -#define IRQ_FLAG ((unsigned *)0xf3000020) -#define IRQ_ENABLE ((unsigned *)0xf3000024) -#define IRQ_ACK ((unsigned *)0xf3000028) -#define IRQ_LEVEL ((unsigned *)0xf300002c) - -#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */ - -#undef SHOW_IRQ 1 +#undef SHOW_IRQ unsigned lost_interrupts = 0; @@ -51,100 +42,114 @@ static struct irqaction irq_action[32]; /* - * This contains the irq mask for both irq controllers + * These are set to the appropriate functions by init_IRQ() */ -static unsigned int cached_irq_mask = 0xffff; - -#define cached_21 (((char *)(&cached_irq_mask))[0]) -#define cached_A1 (((char *)(&cached_irq_mask))[1]) - +void (*mask_and_ack_irq)(int irq_nr); +void (*set_irq_mask)(int irq_nr); +static unsigned int cached_irq_mask = 0xffffffff; +#define cached_21 (((char *)(&cached_irq_mask))[3]) +#define cached_A1 (((char *)(&cached_irq_mask))[2]) +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } int __ppc_bh_counter; -void *null_handler(int,void *,struct pt_regs *); +/* prep */ +#define PREP_IRQ_MASK (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21 +extern unsigned long route_pci_interrupts(void); -/* - * disable and enable intrs in software. This is used - * from the non-realtime parts of Linux to disable interrupts. - * The realtime part disables/enables intrs in the hardware. - * -- Cort - */ -unsigned long soft_intr_enable = 1; -void _soft_cli(void) -{ - soft_intr_enable = 0; -} +/* pmac */ +#define IRQ_FLAG ((unsigned *)0xf3000020) +#define IRQ_ENABLE ((unsigned *)0xf3000024) +#define IRQ_ACK ((unsigned *)0xf3000028) +#define IRQ_LEVEL ((unsigned *)0xf300002c) +#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */ +#define PMAC_IRQ_MASK (~ld_le32(IRQ_ENABLE)) -void _soft_sti(void) +void prep_mask_and_ack_irq(int irq_nr) { - soft_intr_enable = 1; - if ( lost_interrupts ) - { - printk("lost_interrupts from _soft_sti() %x\n",lost_interrupts); - fake_interrupt(); + spin_lock(&irq_controller_lock); + cached_irq_mask |= 1 << irq_nr; + if (irq_nr > 7) { + inb(0xA1); /* DUMMY */ + outb(cached_A1,0xA1); + outb(0x62,0x20); /* Specific EOI to cascade */ + /*outb(0x20,0xA0);*/ + outb(0x60|(irq_nr-8), 0xA0); /* specific eoi */ + } else { + inb(0x21); /* DUMMY */ + outb(cached_21,0x21); + /*outb(0x20,0x20);*/ + outb(0x60|irq_nr,0x20); /* specific eoi */ + } + spin_unlock(&irq_controller_lock); } -void * -null_handler(int a, void *b, struct pt_regs *regs) +void pmac_mask_and_ack_irq(int irq_nr) { - /*printk("irq.c: null_handler() called. Should not have happened.\n");*/ + spin_lock(&irq_controller_lock); + cached_irq_mask |= 1 << irq_nr; + out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr)); + out_le32(IRQ_ACK, 1U << irq_nr); + spin_unlock(&irq_controller_lock); } -void -disable_irq(unsigned int irq_nr) +void prep_set_irq_mask(int irq_nr) { - int s = _disable_interrupts(); - unsigned char mask; - -#ifdef CONFIG_PMAC - out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr)); -#else /* CONFIG_PMAC */ - mask = 1 << (irq_nr & 7); - if (irq_nr < 8) - { - cached_21 |= mask; - outb(cached_21,0x21); - } else - { - cached_A1 |= mask; + if (irq_nr > 7) { outb(cached_A1,0xA1); - } -#endif /* CONFIG_PMAC */ - _enable_interrupts(s); + } else { + outb(cached_21,0x21); + } } -void -enable_irq(unsigned int irq_nr) +void pmac_set_irq_mask(int irq_nr) { - int s = _disable_interrupts(); -#ifdef CONFIG_PMAC - unsigned bit = 1U << irq_nr; - - out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr)); - out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) | bit); - + /* this could be being enabled or disabled - so use cached_irq_mask */ + out_le32(IRQ_ENABLE, ~cached_irq_mask /* enable all unmasked */ ); /* * Unfortunately, setting the bit in the enable register * when the device interrupt is already on *doesn't* set * the bit in the flag register or request another interrupt. */ - if ((ld_le32(IRQ_LEVEL) & bit) && !(ld_le32(IRQ_FLAG) & bit)) - lost_interrupts |= bit; -#else /* CONFIG_PMAC */ - if (irq_nr < 8) { - cached_21 &= ~(1 << (irq_nr & 7)); - outb(cached_21,0x21); - } else - { - cached_A1 &= ~(1 << (irq_nr-8 & 7)); - outb(cached_A1,0xA1); - } -#endif /* CONFIG_PMAC */ + if ((ld_le32(IRQ_LEVEL) & (1UL<handler) + if (!action || !action->handler) continue; len += sprintf(buf+len, "%2d: %10u %s", i, kstat.interrupts[i], action->name); @@ -162,152 +167,99 @@ } len += sprintf(buf+len, "\n"); } -/* - * Linus - should you add NMI counts here ????? - */ #ifdef __SMP_PROF__ len+=sprintf(buf+len, "IPI: %8lu received\n", ipi_count); -#endif +#endif return len; } -asmlinkage void handle_IRQ(struct pt_regs *regs) +asmlinkage void do_IRQ(struct pt_regs *regs) { int irq; - unsigned bits; + unsigned long bits; struct irqaction *action; int cpu = smp_processor_id(); + int status; hardirq_enter(cpu); -#ifdef CONFIG_PMAC - bits = ld_le32(IRQ_FLAG) | lost_interrupts; - lost_interrupts = 0; - - for (irq = NR_IRQS; irq >= 0; --irq) - if (bits & (1U << irq)) - break; -#else /* CONFIG_PMAC */ -#if 1 - if ( lost_interrupts ) + if ( _machine == _MACH_Pmac ) { - irq = ffz(~lost_interrupts); - lost_interrupts &= ~irq; - goto retry; - } - outb(0x0C, 0x20); - irq = inb(0x20) & 7; - if (irq == 2) - { -retry_cascade: - outb(0x0C, 0xA0); - irq = inb(0xA0); - /* if no intr left */ - if ( !(irq & 128 ) ) - goto out; - irq = (irq&7) + 8; + bits = ld_le32(IRQ_FLAG) | lost_interrupts; + lost_interrupts = 0; } -retry: -#else - /* get the irr from the intr controller */ - outb(0x0A, 0x20); - bits = inb(0x20); - /* handle cascade */ - if ( bits ) + else /* prep */ { - bits &= 4; - outb(0x0A, 0xA0); - bits = inb(0xA0)<<8; - } - /* get lost interrupts */ - bits |= lost_interrupts; - /* save intrs that are masked out */ - lost_interrupts = bits & cached_irq_mask; - /* get rid of intrs being masked */ - bits &= ~cached_irq_mask; - /* non-specifc eoi */ - outb(0x20,0x20); - if ( bits & 0xff00 ) - outb(0x20,0xA0); - - printk("bits %04X lost %04X mask %04x\n", - bits, lost_interrupts,cached_irq_mask); +#if 1 + outb(0x0C, 0x20); + irq = inb(0x20) & 7; + if (irq == 2) + { +retry_cascade: + outb(0x0C, 0xA0); + irq = inb(0xA0); + /* if no intr left */ + if ( !(irq & 128 ) ) + goto out; + irq = (irq&7) + 8; + } + bits = 1UL << irq; +#else + /* + * get the isr from the intr controller since + * the bit in the irr has been cleared + */ + outb(0x0a, 0x20); + bits = inb(0x20)&0xff; + /* handle cascade */ + if ( bits & 4 ) + { + bits &= ~4UL; + outb(0x0a, 0xA0); + bits |= inb(0xA0)<<8; + } + /* ignore masked irqs */ + bits &= ~cached_irq_mask; +#endif + } - for (irq = NR_IRQS; irq >= 0; --irq) + for (irq = NR_IRQS - 1; irq >= 0; --irq) if (bits & (1U << irq)) break; -#endif -#endif /* CONFIG_PMAC */ - + if (irq < 0) { - printk("Bogus interrupt from PC = %lx, irq %d\n",regs->nip,irq); + printk("Bogus interrupt from PC = %lx\n", regs->nip); goto out; } -#ifdef CONFIG_PMAC - out_le32(IRQ_ACK, 1U << irq); -#else /* CONFIG_PMAC */ - /* mask out the irq while handling it */ - disable_irq(irq); - /* - * send eoi to interrupt controller right away or lower - * priority intrs would be ignored even if with intrs enabled - */ - if (irq > 7) - { - outb(0xE0|(irq-8), 0xA0); - outb(0xE2, 0x20); - } else - { - outb(0xE0|irq, 0x20); - } -#endif /* !CONFIG_PMAC */ + mask_and_ack_irq(irq); - /* - * now that we've acked the irq, if intrs are disabled in software - * we're in the real-time system and non-rt linux has disabled them - * so we just queue it up and return -- Cort - */ - if ( ! soft_intr_enable ) - { - lost_interrupts |= 1UL << irq; - /* can't printk - kernel expects intrs off! */ - /*printk("irq %d while intrs soft disabled\n", irq);*/ - goto out; - } - - action = irq + irq_action; + status = 0; + action = irq_action + irq; kstat.interrupts[irq]++; - if (action->handler) { + if ( action ) + { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + status |= action->flags; action->handler(irq, action->dev_id, regs); - _disable_interrupts(); /* in case the handler turned them on */ + /*if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq);*/ + __cli(); /* in case the handler turned them on */ + spin_lock(&irq_controller_lock); + unmask_irq(irq); + spin_unlock(&irq_controller_lock); } else { disable_irq( irq ); } -#ifdef CONFIG_PREP - /* re-enable if the interrupt was good and isn't one-shot */ - if ( action->handler && !(action->flags & SA_ONESHOT) ) - enable_irq(irq); + /* make sure we don't miss any cascade intrs due to eoi-ing irq 2 */ - if ( irq > 7 ) + if ( (_machine != _MACH_Pmac)/*prep*/ && (irq > 7) ) goto retry_cascade; -#endif - - hardirq_exit(cpu); - /* - * This should be conditional: we should really get - * a return code from the irq handler to tell us - * whether the handler wants us to do software bottom - * half handling or not.. - */ - if (1) - if (bh_active & bh_mask) - do_bottom_half(); - return; + /* do_bottom_half is called if necessary from int_return in head.S */ out: hardirq_exit(cpu); - } int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), @@ -315,13 +267,13 @@ { struct irqaction * action; unsigned long flags; - -#ifdef SHOW_IRQ + +#ifdef SHOW_IRQ printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n", irq,handler,devname,dev_id); #endif /* SHOW_IRQ */ - - if (irq > NR_IRQS) + + if (irq >= NR_IRQS) return -EINVAL; action = irq + irq_action; if (action->handler) @@ -339,17 +291,16 @@ restore_flags(flags); return 0; } - void free_irq(unsigned int irq, void *dev_id) { struct irqaction * action = irq + irq_action; unsigned long flags; -#ifdef SHOW_IRQ +#ifdef SHOW_IRQ printk("free_irq(): irq %d dev_id %04x\n", irq, dev_id); #endif /* SHOW_IRQ */ - - if (irq > NR_IRQS) { + + if (irq >= NR_IRQS) { printk("Trying to free IRQ%d\n",irq); return; } @@ -370,114 +321,85 @@ unsigned long probe_irq_on (void) { - unsigned int i, irqs = 0, irqmask; - unsigned long delay; - - /* first, snaffle up any unassigned irqs */ - for (i = 15; i > 0; i--) { - if (!request_irq(i, null_handler, SA_ONESHOT, "probe", NULL)) { - enable_irq(i); - irqs |= (1 << i); - } - } - - /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + 2; delay > jiffies; ); /* min 10ms delay */ - - /* now filter out any obviously spurious interrupts */ - irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21; - for (i = 15; i > 0; i--) { - if (irqs & (1 << i) & irqmask) { - irqs ^= (1 << i); - free_irq(i, NULL); - } - } -#ifdef DEBUG - printk("probe_irq_on: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - return irqs; + return 0; } int probe_irq_off (unsigned long irqs) { - unsigned int i, irqmask; - - irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21; - for (i = 15; i > 0; i--) { - if (irqs & (1 << i)) { - free_irq(i, NULL); - } - } -#ifdef SHOW_IRQ - printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - irqs &= irqmask; - if (!irqs) - return 0; - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - return i; + return 0; } -void init_IRQ(void) +__initfunc(void init_IRQ(void)) { -#ifdef CONFIG_PMAC extern void xmon_irq(int, void *, struct pt_regs *); - *IRQ_ENABLE = 0; - request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0); -#else /* CONFIG_PMAC */ - /* Initialize interrupt controllers */ - outb(0x11, 0x20); /* Start init sequence */ - outb(0x40, 0x21); /* Vector base */ -#if 1 - outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ -#else - outb(0x0C, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ -#endif - - outb(0x01, 0x21); /* Select 8086 mode */ - outb(0xFF, 0x21); /* Mask all */ - - outb(0x11, 0xA0); /* Start init sequence */ - outb(0x48, 0xA1); /* Vector base */ -#if 1 - outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */ -#else - outb(0x0A, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ -#endif - outb(0x01, 0xA1); /* Select 8086 mode */ - outb(0xFF, 0xA1); /* Mask all */ + if ( _machine == _MACH_Pmac ) + { + mask_and_ack_irq = pmac_mask_and_ack_irq; + set_irq_mask = pmac_set_irq_mask; + + *IRQ_ENABLE = 0; +#ifdef CONFIG_XMON + request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0); +#endif /* CONFIG_XMON */ + } + else /* prep */ + { + mask_and_ack_irq = prep_mask_and_ack_irq; + set_irq_mask = prep_set_irq_mask; + + /* init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence */ + outb(0x40, 0x21); /* Vector base */ + /*outb(0x04, 0x21);*/ /* edge tiggered, Cascade (slave) on IRQ2 */ + outb(0x0C, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0x21); /* Select 8086 mode */ + outb(0xFF, 0x21); /* Mask all */ + + /* init slave interrupt controller */ + outb(0x11, 0xA0); /* Start init sequence */ + outb(0x48, 0xA1); /* Vector base */ + /*outb(0x02, 0xA1);*/ /* edge triggered, Cascade (slave) on IRQ2 */ + outb(0x0A, 0x21); /* level triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0xA1); /* Select 8086 mode */ + outb(0xFF, 0xA1); /* Mask all */ + + /* + * According to the Carolina spec from ibm irq's 0,1,2, and 8 + * must be edge triggered. Also, the pci intrs must be level + * triggered and _only_ isa intrs can be level sensitive + * which are 3-7,9-12,14-15. 13 is special - it can be level. + * + * power on default is 0's in both regs - all edge. + * + * These edge/level control regs allow edge/level status + * to be decided on a irq basis instead of on a PIC basis. + * It's still pretty ugly. + * - Cort + */ + { + unsigned char irq_mode1 = 0, irq_mode2 = 0; + irq_mode1 = 0; /* to get rid of compiler warnings */ + /* + * On Carolina, irq 15 and 13 must be level (scsi/ide/net). + */ + if ( _machine == _MACH_IBM ) + irq_mode2 |= 0xa0; + /* + * Sound on the Powerstack reportedly needs to be edge triggered + */ + if ( _machine == _MACH_Motorola ) + {} - /* - * Program level mode for irq's that 'can' be level triggered. - * This does not effect irq's 0,1,2 and 8 since they must be - * edge triggered. This is not the PIC controller. The default - * here is for edge trigger mode. -- Cort - */ -#if 0 - outb(0xf8, 0x4d0); /* level triggered */ - outb(0xff, 0x4d1); -#endif -#if 0 - outb(0x00, 0x4D0); /* All edge triggered */ - outb(0xCF, 0x4D1); /* Trigger mode */ -#endif - outb(cached_A1, 0xA1); - outb(cached_21, 0x21); - if (request_irq(2, null_handler, SA_INTERRUPT, "cascade", NULL)) - printk("Unable to get IRQ2 for cascade\n"); - enable_irq(2); /* Enable cascade interrupt */ - -#define TIMER0_COUNT 0x40 -#define TIMER_CONTROL 0x43 - /* set timer to periodic mode */ - outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */ - /* set the clock to ~100 Hz */ - outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ - outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ + /*outb( irq_mode1 , 0x4d0 ); + outb( irq_mode2 , 0x4d1 );*/ + } + outb(cached_A1, 0xA1); + outb(cached_21, 0x21); + if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL) != 0) + panic("Could not allocate cascade IRQ!"); + enable_irq(2); /* Enable cascade interrupt */ - route_pci_interrupts(); -#endif /* CONFIG_PMAC */ + route_pci_interrupts(); + } } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ksyms.c linux/arch/ppc/kernel/ksyms.c --- v2.1.50/linux/arch/ppc/kernel/ksyms.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ksyms.c Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -void transfer_to_handler(); -void int_return(); -void syscall_trace(); -void handle_IRQ(); -void MachineCheckException(); -void AlignmentException(); -void ProgramCheckException(); -void SingleStepException(); -void FloatingPointCheckException(); -void sys_sigreturn(); -unsigned long sys_call_table[]; - -extern struct task_struct *current_set[1]; - -/* platform dependent support */ -EXPORT_SYMBOL(current_set); -EXPORT_SYMBOL(do_signal); -EXPORT_SYMBOL(syscall_trace); -EXPORT_SYMBOL(transfer_to_handler); -EXPORT_SYMBOL(int_return); -EXPORT_SYMBOL(handle_IRQ); -EXPORT_SYMBOL(init_task_union); -EXPORT_SYMBOL(MachineCheckException); -EXPORT_SYMBOL(AlignmentException); -EXPORT_SYMBOL(ProgramCheckException); -EXPORT_SYMBOL(SingleStepException); -EXPORT_SYMBOL(FloatingPointCheckException); -EXPORT_SYMBOL(sys_sigreturn); -EXPORT_SYMBOL(sys_call_table); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.1.50/linux/arch/ppc/kernel/misc.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/misc.S Sat Aug 16 09:51:08 1997 @@ -64,6 +64,7 @@ mtmsr r3 /* Update machine state */ blr +#if 0 /* * Restore 'flags' * __restore_flags(long val) @@ -79,11 +80,13 @@ mtmsr r3 isync blr - +#endif + /* * We were about to enable interrupts but we have to simulate * some interrupts that were lost by enable_irq first. */ + .globl do_lost_interrupts do_lost_interrupts: stwu r1,-16(r1) mflr r0 @@ -243,7 +246,6 @@ bdnz 00b blr -#ifdef CONFIG_PMAC _GLOBAL(ide_insw) mtctr r5 subi r4,r4,2 @@ -259,7 +261,6 @@ sthx r5,0,r3 bdnz 00b blr -#endif /* * Extended precision shifts @@ -298,7 +299,7 @@ _GLOBAL(_get_SP) mr r3,r1 /* Close enough */ blr - + _GLOBAL(_get_PVR) mfspr r3,PVR blr @@ -308,6 +309,7 @@ lfs 0,0(r3) stfd 0,0(r4) blr + /* * Fetch the current SR register * get_SR(int index) @@ -317,7 +319,6 @@ mr r3,r4 blr - _GLOBAL(cvt_df) cvt_df: lfd 0,0(r3) diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c --- v2.1.50/linux/arch/ppc/kernel/mk_defs.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/mk_defs.c Sat Aug 16 09:51:08 1997 @@ -29,7 +29,6 @@ void main(void) { - /*DEFINE(KERNELBASE, KERNELBASE);*/ DEFINE(STATE, offsetof(struct task_struct, state)); DEFINE(NEXT_TASK, offsetof(struct task_struct, next_task)); DEFINE(COUNTER, offsetof(struct task_struct, counter)); @@ -37,54 +36,20 @@ DEFINE(SIGNAL, offsetof(struct task_struct, signal)); DEFINE(TSS, offsetof(struct task_struct, tss)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); - DEFINE(PG_TABLES, offsetof(struct thread_struct, pg_tables)); -#ifdef CONFIG_PMAC - DEFINE(LAST_PC, offsetof(struct thread_struct, last_pc)); - DEFINE(USER_STACK, offsetof(struct thread_struct, user_stack)); -#endif + /*DEFINE(PG_TABLES, offsetof(struct thread_struct, pg_tables));*/ + DEFINE(MM, offsetof(struct task_struct, mm)); + DEFINE(PGD, offsetof(struct mm_struct, pgd)); DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(PF_TRACESYS, PF_TRACESYS); DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0])); -#if 0 - DEFINE(TSS_FPR1, offsetof(struct thread_struct, fpr[1])); - DEFINE(TSS_FPR2, offsetof(struct thread_struct, fpr[2])); - DEFINE(TSS_FPR3, offsetof(struct thread_struct, fpr[3])); - DEFINE(TSS_FPR4, offsetof(struct thread_struct, fpr[4])); - DEFINE(TSS_FPR5, offsetof(struct thread_struct, fpr[5])); - DEFINE(TSS_FPR6, offsetof(struct thread_struct, fpr[6])); - DEFINE(TSS_FPR7, offsetof(struct thread_struct, fpr[7])); - DEFINE(TSS_FPR8, offsetof(struct thread_struct, fpr[8])); - DEFINE(TSS_FPR9, offsetof(struct thread_struct, fpr[9])); - DEFINE(TSS_FPR10, offsetof(struct thread_struct, fpr[10])); - DEFINE(TSS_FPR11, offsetof(struct thread_struct, fpr[11])); - DEFINE(TSS_FPR12, offsetof(struct thread_struct, fpr[12])); - DEFINE(TSS_FPR13, offsetof(struct thread_struct, fpr[13])); - DEFINE(TSS_FPR14, offsetof(struct thread_struct, fpr[14])); - DEFINE(TSS_FPR15, offsetof(struct thread_struct, fpr[15])); - DEFINE(TSS_FPR16, offsetof(struct thread_struct, fpr[16])); - DEFINE(TSS_FPR17, offsetof(struct thread_struct, fpr[17])); - DEFINE(TSS_FPR18, offsetof(struct thread_struct, fpr[18])); - DEFINE(TSS_FPR19, offsetof(struct thread_struct, fpr[19])); - DEFINE(TSS_FPR20, offsetof(struct thread_struct, fpr[20])); - DEFINE(TSS_FPR21, offsetof(struct thread_struct, fpr[21])); - DEFINE(TSS_FPR22, offsetof(struct thread_struct, fpr[22])); - DEFINE(TSS_FPR23, offsetof(struct thread_struct, fpr[23])); - DEFINE(TSS_FPR24, offsetof(struct thread_struct, fpr[24])); - DEFINE(TSS_FPR25, offsetof(struct thread_struct, fpr[25])); - DEFINE(TSS_FPR26, offsetof(struct thread_struct, fpr[26])); - DEFINE(TSS_FPR27, offsetof(struct thread_struct, fpr[27])); - DEFINE(TSS_FPR28, offsetof(struct thread_struct, fpr[28])); - DEFINE(TSS_FPR29, offsetof(struct thread_struct, fpr[29])); - DEFINE(TSS_FPR30, offsetof(struct thread_struct, fpr[30])); - DEFINE(TSS_FPR31, offsetof(struct thread_struct, fpr[31])); -#endif DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr)); /* Interrupt register frame */ DEFINE(TASK_UNION_SIZE, sizeof(union task_union)); DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); + /* in fact we only use gpr0 - gpr9 and gpr20 - gpr23 */ DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0])); DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1])); DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2])); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pci-bridge.c linux/arch/ppc/kernel/pci-bridge.c --- v2.1.50/linux/arch/ppc/kernel/pci-bridge.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/pci-bridge.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,428 @@ +/* + * Support for PCI bridges found on Power Macintoshes. + * At present the "bandit" and "chaos" bridges are supported. + * Fortunately you access configuration space in the same + * way with either bridge. + * + * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) + * + * 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 +#include + +struct bridge_data { + volatile unsigned int *cfg_addr; + volatile unsigned char *cfg_data; + void *io_base; + int bus_number; + int max_bus; + struct bridge_data *next; + struct device_node *node; +}; + +static struct bridge_data **bridges, *bridge_list; +static int max_bus; + +static void add_bridges(struct device_node *dev, unsigned long *mem_ptr); + +/* + * Magic constants for enabling cache coherency in the bandit/PSX bridge. + */ +#define APPLE_VENDID 0x106b +#define BANDIT_DEVID 1 +#define BANDIT_REVID 3 + +#define BANDIT_DEVNUM 11 +#define BANDIT_MAGIC 0x50 +#define BANDIT_COHERENT 0x40 + +/* + * For a bandit bridge, turn on cache coherency if necessary. + * N.B. we can't use pcibios_*_config_* here because bridges[] + * is not initialized yet. + */ +static void init_bandit(struct bridge_data *bp) +{ + unsigned int vendev, magic; + int rev; + + /* read the word at offset 0 in config space for device 11 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); + udelay(2); + vendev = in_le32((volatile unsigned int *)bp->cfg_data); + if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) { + printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); + return; + } + + /* read the revision id */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); + udelay(2); + rev = in_8(bp->cfg_data); + if (rev != BANDIT_REVID) + printk(KERN_WARNING "Unknown revision %d for bandit at %p\n", + rev, bp->io_base); + + /* read the word at offset 0x50 */ + out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); + udelay(2); + magic = in_le32((volatile unsigned int *)bp->cfg_data); + if ((magic & BANDIT_COHERENT) != 0) + return; + magic |= BANDIT_COHERENT; + udelay(2); + out_le32((volatile unsigned int *)bp->cfg_data, magic); + printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n", + bp->io_base); +} + +unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end) +{ + int bus; + struct bridge_data *bridge; + + bridge_list = 0; + max_bus = 0; + add_bridges(find_devices("bandit"), &mem_start); + add_bridges(find_devices("chaos"), &mem_start); + bridges = (struct bridge_data **) mem_start; + mem_start += (max_bus + 1) * sizeof(struct bridge_data *); + memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *)); + for (bridge = bridge_list; bridge != NULL; bridge = bridge->next) + for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus) + bridges[bus] = bridge; + + return mem_start; +} + +static void add_bridges(struct device_node *dev, unsigned long *mem_ptr) +{ + int *bus_range; + int len; + struct bridge_data *bp; + + for (; dev != NULL; dev = dev->next) { + if (dev->n_addrs < 1) { + printk(KERN_WARNING "Can't use %s: no address\n", + dev->full_name); + continue; + } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + dev->full_name); + continue; + } + if (bus_range[1] == bus_range[0]) + printk(KERN_INFO "PCI bus %d", bus_range[0]); + else + printk(KERN_INFO "PCI buses %d..%d", bus_range[0], + bus_range[1]); + printk(" controlled by %s at %x\n", + dev->name, dev->addrs[0].address); + bp = (struct bridge_data *) *mem_ptr; + *mem_ptr += sizeof(struct bridge_data); + bp->cfg_addr = (volatile unsigned int *) + (dev->addrs[0].address + 0x800000); + bp->cfg_data = (volatile unsigned char *) + (dev->addrs[0].address + 0xc00000); + bp->io_base = (void *) dev->addrs[0].address; + ioremap(dev->addrs[0].address, 0x800000); + bp->bus_number = bus_range[0]; + bp->max_bus = bus_range[1]; + bp->next = bridge_list; + bp->node = dev; + bridge_list = bp; + if (bp->max_bus > max_bus) + max_bus = bp->max_bus; + + if (strcmp(dev->name, "bandit") == 0) + init_bandit(bp); + } +} + +void *pci_io_base(unsigned int bus) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0) + return 0; + return bp->io_base; +} + +int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, + unsigned char *devfn_ptr) +{ + unsigned int *reg; + int len; + + reg = (unsigned int *) get_property(dev, "reg", &len); + if (reg == 0 || len < 5 * sizeof(unsigned int)) { + /* doesn't look like a PCI device */ + *bus_ptr = 0xff; + *devfn_ptr = 0xff; + return -1; + } + *bus_ptr = reg[0] >> 16; + *devfn_ptr = reg[0] >> 8; + return 0; +} + +int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val) +{ + struct bridge_data *bp; + + *val = 0xff; + if (bus > max_bus || (bp = bridges[bus]) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + *val = in_8(bp->cfg_data + (offset & 3)); + + if (offset == PCI_INTERRUPT_LINE) { + /* + * Open Firmware often doesn't initialize this + * register properly, so we find the node and see + * if it has an AAPL,interrupts property. + */ + struct device_node *node; + unsigned int *reg; + + for (node = bp->node->child; node != 0; node = node->sibling) { + reg = (unsigned int *) get_property(node, "reg", 0); + if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev_fn) + continue; + /* this is the node, see if it has interrupts */ + if (node->n_intrs > 0) + *val = node->intrs[0]; + break; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val) +{ + struct bridge_data *bp; + + *val = 0xffff; + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 1) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + *val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3))); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val) +{ + struct bridge_data *bp; + + *val = 0xffffffff; + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 3) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + offset); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + offset + 1); + } + udelay(2); + *val = in_le32((volatile unsigned int *)bp->cfg_data); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + out_8(bp->cfg_data + (offset & 3), val); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 1) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + (offset & ~3)); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + (offset & ~3) + 1); + } + udelay(2); + out_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)), val); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val) +{ + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 3) != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == bp->bus_number) { + if (dev_fn < (11 << 3)) + return PCIBIOS_DEVICE_NOT_FOUND; + out_le32(bp->cfg_addr, + (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8) + + offset); + } else { + out_le32(bp->cfg_addr, (dev_fn << 8) + offset + 1); + } + udelay(2); + out_le32((volatile unsigned int *)bp->cfg_data, val); + return PCIBIOS_SUCCESSFUL; +} + +int pmac_pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr) +{ + int bus, unit, fn, num, devfn; + unsigned int x, vendev; + unsigned char h; + + if (vendor == 0xffff) + return PCIBIOS_BAD_VENDOR_ID; + vendev = (dev_id << 16) + vendor; + num = 0; + for (bus = 0; bus <= max_bus; ++bus) { + if (bridges[bus] == 0) + continue; + unit = fn = 0; + if (bus == bridges[bus]->bus_number) + unit = 11; + while (unit < 32) { + devfn = PCI_DEVFN(unit, fn); + if (pcibios_read_config_dword(bus, devfn, + PCI_VENDOR_ID, &x) + == PCIBIOS_SUCCESSFUL && x == vendev) { + if (index == num) { + *bus_ptr = bus; + *dev_fn_ptr = devfn; + return PCIBIOS_SUCCESSFUL; + } + ++num; + } + if (fn != 0) { + if (++fn >= 8) { + ++unit; + fn = 0; + } + continue; + } + if (pcibios_read_config_byte(bus, devfn, + PCI_HEADER_TYPE, &h) + == PCIBIOS_SUCCESSFUL && (h & 0x80) != 0) + ++fn; + else + ++unit; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +int pmac_pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr) +{ + int bus, unit, fn, num, devfn; + unsigned int x; + unsigned char h; + + num = 0; + for (bus = 0; bus <= max_bus; ++bus) { + if (bridges[bus] == 0) + continue; + unit = fn = 0; + if (bus == bridges[bus]->bus_number) + unit = 11; + while (unit < 32) { + devfn = PCI_DEVFN(unit, fn); + if (pcibios_read_config_dword(bus, devfn, + PCI_CLASS_REVISION, &x) + == PCIBIOS_SUCCESSFUL && (x >> 8) == class_code) { + if (index == num) { + *bus_ptr = bus; + *dev_fn_ptr = devfn; + return PCIBIOS_SUCCESSFUL; + } + ++num; + } + if (fn != 0) { + if (++fn >= 8) { + ++unit; + fn = 0; + } + continue; + } + if (pcibios_read_config_byte(bus, devfn, + PCI_HEADER_TYPE, &h) + == PCIBIOS_SUCCESSFUL && (h & 0x80) != 0) + ++fn; + else + ++unit; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +__initfunc(unsigned long route_pci_interrupts(void)) +{ + return 0; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.1.50/linux/arch/ppc/kernel/pci.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pci.c Sat Aug 16 09:51:08 1997 @@ -1,630 +1,164 @@ /* - * PCI support - * -- rough emulation of "PCI BIOS" functions - * - * Note: these are very motherboard specific! Some way needs to - * be worked out to handle the differences. + * $Id: pci.c,v 1.11 1997/08/13 03:06:14 cort Exp $ + * Common pmac/prep pci routines. -- Cort */ -#include -#include -#include +#include #include +/*#include */ +#include +#include +#include -#include -#include -#include #include +#include +#include +#include -/* - * PCI interrupt configuration. This is motherboard specific. - */ -/* Which PCI interrupt line does a given device [slot] use? */ -/* Note: This really should be two dimensional based in slot/pin used */ -unsigned char *Motherboard_map; -unsigned char *Motherboard_map_name; - -/* How is the 82378 PIRQ mapping setup? */ -unsigned char *Motherboard_routes; - -/* Tables for known hardware */ - -/* Motorola PowerStack */ -static char Blackhawk_pci_IRQ_map[16] = -{ - 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 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 1, /* Slot 14 - Ethernet */ - 0, /* Slot 15 - unused */ -}; - -static char Blackhawk_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 9, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* Motorola MVME16xx */ -static char Genesis_pci_IRQ_map[16] = -{ - 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 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 1, /* Slot 14 - Ethernet */ - 0, /* Slot 15 - unused */ -}; - -static char Genesis_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 10, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* Motorola Series-E */ -static char Comet_pci_IRQ_map[16] = -{ - 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 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 1, /* Slot 14 - Ethernet */ - 0, /* Slot 15 - unused */ -}; - -static char Comet_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 10, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* BeBox */ -static char BeBox_pci_IRQ_map[16] = -{ - 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 - unused */ - 16, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 0, /* Slot 14 - unused */ - 0, /* Slot 15 - unused */ -}; - -static char BeBox_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 9, /* Line 1 */ - 11, /* Line 2 */ - 14, /* Line 3 */ - 15 /* Line 4 */ -}; - -/* IBM Nobis */ -static char Nobis_pci_IRQ_map[16] = -{ - 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 - unused */ - 3, /* Slot 12 - SCSI */ - 0, /* Slot 13 - unused */ - 0, /* Slot 14 - unused */ - 0, /* Slot 15 - unused */ -}; - -static char Nobis_pci_IRQ_routes[] = -{ - 0, /* Line 0 - Unused */ - 13, /* Line 1 */ - 13, /* Line 2 */ - 13, /* Line 3 */ - 13 /* Line 4 */ -}; - +unsigned long io_base; /* - * ibm 830 (and 850?). - * This is actually based on the Carolina motherboard - * -- Cort - */ -static char ibm8xx_pci_IRQ_map[23] = { - 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 - FireCoral */ - 4, /* Slot 12 - Ethernet PCIINTD# */ - 2, /* Slot 13 - PCI Slot #2 */ - 2, /* Slot 14 - S3 Video PCIINTD# */ - 0, /* Slot 15 - onboard SCSI (INDI) [1] */ - 3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */ - 0, /* Slot 17 - unused */ - 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */ - 0, /* Slot 19 - unused */ - 0, /* Slot 20 - unused */ - 0, /* Slot 21 - unused */ - 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ -}; -static char ibm8xx_pci_IRQ_routes[] = { - 0, /* Line 0 - unused */ - 13, /* Line 1 */ - 10, /* Line 2 */ - 15, /* Line 3 */ - 15, /* Line 4 */ -}; -/* This just changes the PCI slots & onboard SCSI + S3 to IRQ10, but - * it really needs some logic to set them to unique IRQ's, or even - * add some logic to the drivers to ask an irq.c routine to re-map - * the IRQ if it needs one to itself... - */ -static char Carolina_PIRQ_routes[] = { - 0xad, /* INTB# = 10, INTA# = 13 */ - 0xff /* INTD# = 15, INTC# = 15 */ -}; -/* We have to turn on LEVEL mode for changed IRQ's */ -/* All PCI IRQ's need to be level mode, so this should be something - * other than hard-coded as well... IRQ's are individually mappable - * to either edge or level. - */ -#define CAROLINA_IRQ_EDGE_MASK_LO 0x00 /* IRQ's 0-7 */ -#define CAROLINA_IRQ_EDGE_MASK_HI 0xA4 /* IRQ's 8-15 [10,13,15] */ -#define PCI_DEVICE_ID_IBM_CORAL 0x000a - -#undef PCI_DEBUG - -#ifdef PCI_STATS -int PCI_conversions[2]; -#endif - - -unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) -{ - return mem_start; -} - -int -pcibios_present (void) -{ -#ifdef PCI_DEBUG - printk("PCI [BIOS] present?\n"); -#endif - return (1); -} - -int -pcibios_read_config_dword (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned int *val) -{ - unsigned long _val; - unsigned long *ptr; - dev >>= 3; -#ifdef PCI_DEBUG - printk("PCI Read config dword[%d.%d.%x] = ", bus, dev, offset); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - *val = 0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned long *)(0x80800000 | (1<>= 3; -#ifdef PCI_DEBUG - printk("PCI Read config word[%d.%d.%x] = ", bus, dev, offset); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - *val = (unsigned short)0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned short *)(0x80800000 | (1<>= 3; - /* Note: the configuration registers don't always have this right! */ - if (offset == PCI_INTERRUPT_LINE) - { - if (Motherboard_map[dev] <= 4) - { - *val = Motherboard_routes[Motherboard_map[dev]]; - /*printk("dev %d map %d route %d\n", - dev,Motherboard_map[dev], - Motherboard_routes[Motherboard_map[dev]]);*/ - } else - { /* Pseudo interrupts [for BeBox] */ - *val = Motherboard_map[dev]; - } -#ifdef PCI_DEBUG - printk("PCI Read Interrupt Line[%d.%d] = %d\n", bus, dev, *val); -#endif - return PCIBIOS_SUCCESSFUL; + * It would be nice if we could create a include/asm/pci.h and have just + * function ptrs for all these in there, but that isn't the case. + * We have a function, pcibios_*() which calls the function ptr ptr_pcibios_*() + * which has been setup by pcibios_init(). This is all to avoid a check + * for pmac/prep every time we call one of these. It should also make the move + * to a include/asm/pcibios.h easier, we can drop the ptr_ on these functions + * and create pci.h + * -- Cort + */ +int (*ptr_pcibios_read_config_byte)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +int (*ptr_pcibios_read_config_word)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +int (*ptr_pcibios_read_config_dword)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +int (*ptr_pcibios_write_config_byte)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +int (*ptr_pcibios_write_config_word)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +int (*ptr_pcibios_write_config_dword)(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); +int (*ptr_pcibios_find_device)(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr); +int (*ptr_pcibios_find_class)(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr); + +extern int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +extern int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +extern int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +extern int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +extern int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +extern int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); +extern int pmac_pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr); +extern int pmac_pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr); + +extern int prep_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val); +extern int prep_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val); +extern int prep_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val); +extern int prep_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val); +extern int prep_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val); +extern int prep_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val); +extern int prep_pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr); +extern int prep_pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr); + + +int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char *val) +{ + return ptr_pcibios_read_config_byte(bus,dev_fn,offset,val); +} +int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short *val) +{ + return ptr_pcibios_read_config_word(bus,dev_fn,offset,val); +} +int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int *val) +{ + return ptr_pcibios_read_config_dword(bus,dev_fn,offset,val); +} +int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned char val) +{ + return ptr_pcibios_write_config_byte(bus,dev_fn,offset,val); +} +int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned short val) +{ + return ptr_pcibios_write_config_word(bus,dev_fn,offset,val); +} +int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, + unsigned char offset, unsigned int val) +{ + return ptr_pcibios_write_config_dword(bus,dev_fn,offset,val); +} +int pcibios_find_device(unsigned short vendor, unsigned short dev_id, + unsigned short index, unsigned char *bus_ptr, + unsigned char *dev_fn_ptr) +{ + return ptr_pcibios_find_device(vendor,dev_id,index,bus_ptr,dev_fn_ptr); +} +int pcibios_find_class(unsigned int class_code, unsigned short index, + unsigned char *bus_ptr, unsigned char *dev_fn_ptr) +{ + return ptr_pcibios_find_class(class_code,index,bus_ptr,dev_fn_ptr); +} + +int pcibios_present(void) +{ + return 1; +} + +__initfunc(unsigned long +pcibios_init(unsigned long mem_start,unsigned long mem_end)) +{ + if ( _machine == _MACH_Pmac ) + { + ptr_pcibios_read_config_byte = pmac_pcibios_read_config_byte; + ptr_pcibios_read_config_word = pmac_pcibios_read_config_word; + ptr_pcibios_read_config_dword = pmac_pcibios_read_config_dword; + ptr_pcibios_write_config_byte = pmac_pcibios_write_config_byte; + ptr_pcibios_write_config_word = pmac_pcibios_write_config_word; + ptr_pcibios_write_config_dword = pmac_pcibios_write_config_dword; + ptr_pcibios_find_device = pmac_pcibios_find_device; + ptr_pcibios_find_class = pmac_pcibios_find_class; + } + else /* prep */ + { + ptr_pcibios_read_config_byte = prep_pcibios_read_config_byte; + ptr_pcibios_read_config_word = prep_pcibios_read_config_word; + ptr_pcibios_read_config_dword = prep_pcibios_read_config_dword; + ptr_pcibios_write_config_byte = prep_pcibios_write_config_byte; + ptr_pcibios_write_config_word = prep_pcibios_write_config_word; + ptr_pcibios_write_config_dword = prep_pcibios_write_config_dword; + ptr_pcibios_find_device = prep_pcibios_find_device; + ptr_pcibios_find_class = prep_pcibios_find_class; } -#ifdef PCI_DEBUG - printk("PCI Read config byte[%d.%d.%x] = ", bus, dev, offset); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - *val = 0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned char *)(0x80800000 | (1<>= 3; - _val = le32_to_cpu(val); -#ifdef PCI_DEBUG - printk("PCI Write config dword[%d.%d.%x] = %x\n", bus, dev, offset, _val); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned long *)(0x80800000 | (1<>= 3; - _val = le16_to_cpu(val); -#ifdef PCI_DEBUG - printk("PCI Write config word[%d.%d.%x] = %x\n", bus, dev, offset, _val); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned short *)(0x80800000 | (1<>= 3; - _val = val; -#ifdef PCI_DEBUG - printk("PCI Write config byte[%d.%d.%x] = %x\n", bus, dev, offset, _val); -#endif - if ((bus != 0) || (dev < 11) || (dev > 16)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned char *)(0x80800000 | (1<>8) == class_code) - { - if (index == indx) - { - *bus = 0; - *dev = dev_nr<<3; -#ifdef PCI_DEBUG - printk(" - device: %x\n", dev_nr); -#endif - return (0); - } - indx++; - } - } -#ifdef PCI_DEBUG - printk(" - not found\n"); -#endif - return PCIBIOS_DEVICE_NOT_FOUND; -} - -const char *pcibios_strerror(int error) -{ - static char buf[32]; - switch (error) - { case PCIBIOS_SUCCESSFUL: - return ("PCI BIOS: no error"); - case PCIBIOS_FUNC_NOT_SUPPORTED: - return ("PCI BIOS: function not supported"); - case PCIBIOS_BAD_VENDOR_ID: - return ("PCI BIOS: bad vendor ID"); - case PCIBIOS_DEVICE_NOT_FOUND: - return ("PCI BIOS: device not found"); - case PCIBIOS_BAD_REGISTER_NUMBER: - return ("PCI BIOS: bad register number"); - case PCIBIOS_SET_FAILED: - return ("PCI BIOS: set failed"); - case PCIBIOS_BUFFER_TOO_SMALL: - return ("PCI BIOS: buffer too small"); - default: - sprintf(buf, "PCI BIOS: invalid error #%d", error); - return(buf); - } -} - -/* - * Note: This routine has to access the PCI configuration space - * for the PCI bridge chip (Intel 82378). - */ -unsigned long pcibios_init(unsigned long mem_start,unsigned long mem_end) -{ return mem_start; } -unsigned long route_pci_interrupts(void) +__initfunc(unsigned long +pcibios_fixup(unsigned long mem_start, unsigned long mem_end)) { - unsigned char *ibc_pirq = (unsigned char *)0x80800860; - unsigned char *ibc_pcicon = (unsigned char *)0x80800840; - extern unsigned long isBeBox[]; - int i; - - if ( _machine == _MACH_Motorola) - { - switch (inb(0x800) & 0xF0) - { - case 0x10: /* MVME16xx */ - Motherboard_map_name = "Genesis"; - Motherboard_map = Genesis_pci_IRQ_map; - Motherboard_routes = Genesis_pci_IRQ_routes; - break; - case 0x20: /* Series E */ - Motherboard_map_name = "Series E"; - Motherboard_map = Comet_pci_IRQ_map; - Motherboard_routes = Comet_pci_IRQ_routes; - break; - case 0x40: /* PowerStack */ - default: /* Can't hurt, can it? */ - Motherboard_map_name = "Blackhawk (Powerstack)"; - Motherboard_map = Blackhawk_pci_IRQ_map; - Motherboard_routes = Blackhawk_pci_IRQ_routes; - break; - } - } else - { - if ( _machine == _MACH_IBM ) - { - unsigned char pl_id; - unsigned long flags; - unsigned index; - unsigned char fn, bus; - unsigned int addr; - unsigned char dma_mode, ide_mode; - int i; - - Motherboard_map_name = "IBM 8xx (Carolina)"; - Motherboard_map = ibm8xx_pci_IRQ_map; - Motherboard_routes = ibm8xx_pci_IRQ_routes; -ll_printk("before loop\n"); - - for (index = 0; - !pcibios_find_device (PCI_VENDOR_ID_IBM, - PCI_DEVICE_ID_IBM_CORAL, - index, &bus, &fn); ++index) - { - pcibios_read_config_dword(bus, fn, 0x10, &addr); - addr &= ~0x3; - outb(0x26, addr); - dma_mode = inb(addr+4); - outb(0x25, addr); - ide_mode = inb(addr+4); - /*printk("CORAL I/O at 0x%x, DMA mode: %x, IDE mode: %x", - addr, dma_mode, ide_mode);*/ - /* Make CDROM non-DMA */ - ide_mode = (ide_mode & 0x0F) | 0x20; - outb(0x25, addr); - outb(ide_mode, addr+4); - dma_mode = dma_mode & ~0x80; - outb(0x26, addr); - outb(dma_mode, addr+4); - outb(0x26, addr); - dma_mode = inb(addr+4); - outb(0x25, addr); - ide_mode = inb(addr+4); - /*printk("=> DMA mode: %x, IDE mode: %x\n", - dma_mode, ide_mode);*/ - } - - /* Setup the PCI INT mappings for the Carolina */ - /* These are PCI Interrupt Route Control [1|2] Register */ - outb(Carolina_PIRQ_routes[0], 0x0890); - outb(Carolina_PIRQ_routes[1], 0x0891); - - pl_id=inb(0x0852); - /*printk("CPU Planar ID is %#0x\n", pl_id);*/ - - if (pl_id == 0x0C) { - /* INDI */ - Motherboard_map[12] = 1; - } -ll_printk("before edge/level\n"); -#if 0 - /*printk("Changing IRQ mode\n");*/ - pl_id=inb(0x04d0); - /*printk("Low mask is %#0x\n", pl_id);*/ - outb(pl_id|CAROLINA_IRQ_EDGE_MASK_LO, 0x04d0); - - pl_id=inb(0x04d1); - /*printk("Hi mask is %#0x\n", pl_id);*/ - outb(pl_id|CAROLINA_IRQ_EDGE_MASK_HI, 0x04d1); - pl_id=inb(0x04d1); - /*printk("Hi mask now %#0x\n", pl_id);*/ -#endif - } - } - - /* Set up mapping from slots */ - for (i = 1; i <= 4; i++) - { - ibc_pirq[i-1] = Motherboard_routes[i]; - } - /* Enable PCI interrupts */ - *ibc_pcicon |= 0x20; + return mem_start; } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.1.50/linux/arch/ppc/kernel/pmac_setup.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pmac_setup.c Sat Aug 16 09:51:08 1997 @@ -21,6 +21,7 @@ * bootup setup stuff.. */ +#include #include #include #include @@ -35,31 +36,35 @@ #include #include #include +#include #include #include #include #include #include +#include +#include "time.h" + +/* + * A magic address and value to put into it on machines with the + * "ohare" I/O controller. This makes the IDE CD work on Starmaxes. + * Contributed by Harry Eaton. + */ +#define OMAGICPLACE ((volatile unsigned *) 0xf3000038) +#define OMAGICCONT 0xbeff7a extern int root_mountflags; extern char command_line[]; -char saved_command_line[256]; +extern char saved_command_line[256]; -unsigned char aux_device_present; /* XXX */ -unsigned char kbd_read_mask; unsigned char drive_info; #define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */ extern unsigned long find_available_memory(void); -unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) -{ - return memory_start; -} - -void setup_arch(char **cmdline_p, +void pmac_setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) { extern unsigned long *end_of_DRAM; @@ -84,6 +89,8 @@ if (fp != 0) { switch (_get_PVR() >> 16) { case 4: /* 604 */ + case 9: /* 604e */ + case 20: /* 620 */ loops_per_sec = *fp; break; default: /* 601, 603, etc. */ @@ -102,13 +109,19 @@ kdev_t boot_dev; unsigned long -pmac_find_devices(unsigned long mem_start, unsigned long mem_end) +powermac_init(unsigned long mem_start, unsigned long mem_end) { - struct device_node *chosen_np; + struct device_node *chosen_np, *ohare_np; - nvram_init(); + mem_start = pmac_find_bridges(mem_start, mem_end); + ohare_np = find_devices("ohare"); + if (ohare_np != NULL) { + printk(KERN_INFO "Twiddling the magic ohare bits\n"); + out_le32(OMAGICPLACE, OMAGICCONT); + } + pmac_nvram_init(); via_cuda_init(); - read_rtc_time(); + pmac_read_rtc_time(); pmac_find_display(); bootpath = NULL; chosen_np = find_devices("chosen"); @@ -147,7 +160,7 @@ } } -void find_scsi_boot() +void find_boot_device(void) { int dev; @@ -156,10 +169,28 @@ ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); if (boot_host == NULL) return; +#ifdef CONFIG_SCSI dev = sd_find_target(boot_host, boot_target); if (dev == 0) return; boot_dev = to_kdev_t(dev + boot_part); +#endif + /* XXX should cope with booting from IDE also */ +} + +void note_bootable_part(kdev_t dev, int part) +{ + static int found_boot = 0; + + if (!found_boot) { + find_boot_device(); + found_boot = 1; + } + if (dev == boot_dev) { + ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part); + boot_dev = NODEV; + printk(" (root)"); + } } void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) @@ -186,41 +217,18 @@ if (np->n_intrs == 0) { printk("ide: no intrs for device %s, using 13\n", np->full_name); - np->intrs[0] = 13; + *irq = 13; + } else { + *irq = np->intrs[0]; } base = (unsigned long) ioremap(np->addrs[0].address, 0x200); for (i = 0; i < 8; ++i) *p++ = base + i * 0x10; *p = base + 0x160; - *irq = np->intrs[0]; -} - -int sys_ioperm(unsigned long from, unsigned long num, int on) -{ - return -EIO; -} - -#if 0 -extern char builtin_ramdisk_image; -extern long builtin_ramdisk_size; -#endif - -void -builtin_ramdisk_init(void) -{ -#if 0 - if ((ROOT_DEV == to_kdev_t(DEFAULT_ROOT_DEVICE)) && (builtin_ramdisk_size != 0)) - { - rd_preloaded_init(&builtin_ramdisk_image, builtin_ramdisk_size); - } else -#endif - { /* Not ramdisk - assume root needs to be mounted read only */ - root_mountflags |= MS_RDONLY; - } } int -get_cpuinfo(char *buffer) +pmac_get_cpuinfo(char *buffer) { int pvr = _get_PVR(); char *model; @@ -251,10 +259,13 @@ case 7: model = "603ev"; break; + case 9: + model = "604e"; + break; default: model = "unknown"; break; } return l + sprintf(buffer+l, "PowerPC %s rev %d.%d\n", model, - (pvr & 0xff) >> 8, pvr & 0xff); + (pvr & 0xff00) >> 8, pvr & 0xff); } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c --- v2.1.50/linux/arch/ppc/kernel/pmac_support.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pmac_support.c Sat Aug 16 09:51:08 1997 @@ -3,30 +3,14 @@ */ #include #include +#include +#include #include #include #include #include #include -void hard_reset_now(void) -{ - struct cuda_request req; - - cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM); - for (;;) - cuda_poll(); -} - -void poweroff_now(void) -{ - struct cuda_request req; - - cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN); - for (;;) - cuda_poll(); -} - /* * Read and write the non-volatile RAM on PowerMacs. */ @@ -34,26 +18,29 @@ static volatile unsigned char *nvram_addr; static volatile unsigned char *nvram_data; -void nvram_init(void) +void pmac_nvram_init(void) { struct device_node *dp; dp = find_devices("nvram"); - if (dp == NULL) - panic("Can't find NVRAM device"); + if (dp == NULL) { + printk(KERN_ERR "Can't find NVRAM device\n"); + nvram_naddrs = 0; + return; + } nvram_naddrs = dp->n_addrs; - if (nvram_naddrs == 1) + if (nvram_naddrs == 1) { nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); - else if (nvram_naddrs == 2) { + } else if (nvram_naddrs == 2) { nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); } else { - printk("Found %d addresses for NVRAM\n", nvram_naddrs); - panic("don't understand NVRAM"); + printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", + nvram_naddrs); } } -int nvram_readb(int addr) +unsigned char nvram_read_byte(int addr) { switch (nvram_naddrs) { case 1: @@ -63,10 +50,10 @@ eieio(); return nvram_data[(addr & 0x1f) << 4]; } - return -1; + return 0; } -void nvram_writeb(int addr, int val) +void nvram_write_byte(unsigned char val, int addr) { switch (nvram_naddrs) { case 1: diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c --- v2.1.50/linux/arch/ppc/kernel/pmac_time.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/pmac_time.c Sat Aug 16 09:51:08 1997 @@ -19,125 +19,60 @@ #include #include -static int get_dec(void); -static void set_dec(int); -static unsigned long get_rtc_time(void); +#include "time.h" + /* Apparently the RTC stores seconds since 1 Jan 1904 */ #define RTC_OFFSET 2082844800 -/* Accessor functions for the decrementer register. */ -static inline int -get_dec() -{ - int ret; - - asm volatile("mfspr %0,22" : "=r" (ret) :); - return ret; -} - -static inline void -set_dec(int val) -{ - asm volatile("mtspr 22,%0" : : "r" (val)); -} - -/* The decrementer counts down by 128 every 128ns on a 601. */ -#define DECREMENTER_COUNT_601 (1000000000 / HZ) -#define COUNT_PERIOD_NUM_601 1 -#define COUNT_PERIOD_DEN_601 1000 - -unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ -unsigned count_period_num; /* 1 decrementer count equals */ -unsigned count_period_den; /* count_period_num / count_period_den us */ - /* - * This version of gettimeofday has microsecond resolution. + * Query the OF and get the decr frequency. + * This was taken from the pmac time_init() when merging the prep/pmac + * time functions. */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - - save_flags(flags); - cli(); - *tv = xtime; - tv->tv_usec += (decrementer_count - get_dec()) - * count_period_num / count_period_den; - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } - restore_flags(flags); -} - -void do_settimeofday(struct timeval *tv) +void pmac_calibrate_decr(void) { - unsigned long flags; - int frac_tick; + struct device_node *cpu; + int freq, *fp, divisor; - frac_tick = tv->tv_usec % (1000000 / HZ); - save_flags(flags); - cli(); - xtime.tv_sec = tv->tv_sec; - xtime.tv_usec = tv->tv_usec - frac_tick; - set_dec(frac_tick * count_period_den / count_period_num); - restore_flags(flags); + /* + * The cpu node should have a timebase-frequency property + * to tell us the rate at which the decrementer counts. + */ + cpu = find_type_devices("cpu"); + if (cpu == 0) + panic("can't find cpu node in time_init"); + fp = (int *) get_property(cpu, "timebase-frequency", NULL); + if (fp == 0) + panic("can't get cpu timebase frequency"); + freq = *fp * 60; /* try to make freq/1e6 an integer */ + divisor = 60; + printk("time_init: decrementer frequency = %d/%d\n", + freq, divisor); + decrementer_count = freq / HZ / divisor; + count_period_num = divisor; + count_period_den = freq / 1000000; } -/* - * timer_interrupt - gets called when the decrementer overflows, - * with interrupts disabled. - * We set it up to overflow again in 1/HZ seconds. - */ -void timer_interrupt(struct pt_regs * regs) +unsigned long +pmac_get_rtc_time(void) { - int dval, d; - - while ((dval = get_dec()) < 0) { - /* - * Wait for the decrementer to change, then jump - * in and add decrementer_count to its value - * (quickly, before it changes again!) - */ - while ((d = get_dec()) == dval) - ; - set_dec(d + decrementer_count); - do_timer(regs); - } + struct cuda_request req; + /* Get the time from the RTC */ + cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME); + while (!req.got_reply) + cuda_poll(); + if (req.reply_len != 7) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + return (req.reply[3] << 24) + (req.reply[4] << 16) + + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; } -void -time_init(void) +int pmac_set_rtc_time(unsigned long nowtime) { - struct device_node *cpu; - int freq, *fp, divisor; - - if ((_get_PVR() >> 16) == 1) { - /* 601 processor: dec counts down by 128 every 128ns */ - decrementer_count = DECREMENTER_COUNT_601; - count_period_num = COUNT_PERIOD_NUM_601; - count_period_den = COUNT_PERIOD_DEN_601; - } else { - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ - cpu = find_type_devices("cpu"); - if (cpu == 0) - panic("can't find cpu node in time_init"); - fp = (int *) get_property(cpu, "timebase-frequency", NULL); - if (fp == 0) - panic("can't get cpu timebase frequency"); - freq = *fp * 60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %d/%d\n", - freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; - } - set_dec(decrementer_count); + return 0; } /* @@ -145,24 +80,8 @@ * been called at that stage. */ void -read_rtc_time(void) +pmac_read_rtc_time(void) { - xtime.tv_sec = get_rtc_time(); + xtime.tv_sec = pmac_get_rtc_time(); xtime.tv_usec = 0; -} - -static unsigned long -get_rtc_time() -{ - struct cuda_request req; - - /* Get the time from the RTC */ - cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME); - while (!req.got_reply) - cuda_poll(); - if (req.reply_len != 7) - panic("get_rtc_time: didn't expect %d byte reply", - req.reply_len); - return (req.reply[3] << 24) + (req.reply[4] << 16) - + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET; } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/port_io.c linux/arch/ppc/kernel/port_io.c --- v2.1.50/linux/arch/ppc/kernel/port_io.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/port_io.c Wed Dec 31 16:00:00 1969 @@ -1,146 +0,0 @@ -/* - * I/O 'port' access routines - */ -#include -#include - -#define inb_asm(port) {( \ - unsigned char ret; \ - asm ( "lbz %0,0(%1)\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" : "=r" (ret) : "r" (port+_IO_BASE)); \ - return ret; \ -}) - -inline unsigned char -inb(int port) -{ - unsigned char ret; - asm("/*inb*/\n"); - asm ( "lbz %0,0(%1)" : "=r" (ret) : "r" (port+_IO_BASE)); - return ret; -} - -inline unsigned short -inw(int port) -{ - unsigned short ret; - asm("/*inw*/\n"); - asm ( "lhbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0)); - return ret; -} - -inline unsigned long -inl(int port) -{ - unsigned long ret; - asm("/*inl*/\n"); - asm ( "lwbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0)); - return ret; -} - -inline unsigned char -outb(unsigned char val,int port) -{ - asm("/*outb*/\n"); - asm ( "stb %0,0(%1)" :: "r" (val), "r" (port+_IO_BASE)); - return (val); -} - -inline unsigned short -outw(unsigned short val,int port) -{ - asm("/*outw*/\n"); - asm ( "sthbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0)); - return (val); -} - -inline unsigned long -outl(unsigned long val,int port) -{ - asm("/*outl*/\n"); - asm ( "stwbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0)); - return (val); -} - -void insb(int port, char *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), len); -} - -void insw(int port, short *ptr, int len) -{ - asm ("mtctr %2 \n\t" - "subi %1,%1,2 \n\t" - "00:\n\t" - "lhbrx %2,0,%0 \n\t" - "sthu %2,2(%1) \n\t" - "bdnz 00b \n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void insw_unswapped(int port, short *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), (len*sizeof(short)) ); -} - -void insl(int port, long *ptr, int len) -{ - asm ("mtctr %2 \n\t" - "subi %1,%1,4 \n\t" - "00:\n\t" - "lhbrx %2,0,%0 \n\t" - "sthu %2,4(%1) \n\t" - "bdnz 00b \n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void outsb(int port, char *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), len ); -} - -void outsw(int port, short *ptr, int len) -{ - asm ("mtctr %2\n\t" - "subi %1,%1,2\n\t" - "00:lhzu %2,2(%1)\n\t" - "sthbrx %2,0,%0\n\t" - "bdnz 00b\n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void outsw_unswapped(int port, short *ptr, int len) -{ - memcpy( (void *)ptr, (void *)(port+_IO_BASE), len*sizeof(short) ); -} - -void outsl(int port, long *ptr, int len) -{ - asm ("mtctr %2\n\t" - "subi %1,%1,4\n\t" - "00:lwzu %2,4(%1)\n\t" - "sthbrx %2,0,%0\n\t" - "bdnz 00b\n\t" - :: "r" (port+_IO_BASE), "r" (ptr), "r" (len)); -} - -void insl_unswapped(int port, long *ptr, int len) -{ - unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port); - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - while (len-- > 0) - { - *ptr++ = (*io_ptr); - } -} - -void outsl_unswapped(int port, long *ptr, int len) -{ - unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port); - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - while (len-- > 0) - { - *io_ptr = (*ptr++); - } -} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_asm.tmpl linux/arch/ppc/kernel/ppc_asm.tmpl --- v2.1.50/linux/arch/ppc/kernel/ppc_asm.tmpl Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ppc_asm.tmpl Sat Aug 16 09:51:08 1997 @@ -187,7 +187,3 @@ #define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) #define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) #define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) - -/* Missing instructions */ -#define bdne bc 0,2, - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_defs.h linux/arch/ppc/kernel/ppc_defs.h --- v2.1.50/linux/arch/ppc/kernel/ppc_defs.h Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ppc_defs.h Wed Dec 31 16:00:00 1969 @@ -1,63 +0,0 @@ -/* - * WARNING! This file is automatically generated - DO NOT EDIT! - */ -#define STATE 0 -#define NEXT_TASK 68 -#define COUNTER 4 -#define BLOCKED 16 -#define SIGNAL 12 -#define TSS 544 -#define KSP 0 -#define PG_TABLES 4 -#define LAST_SYSCALL 288 -#define PT_REGS 280 -#define PF_TRACESYS 32 -#define TASK_FLAGS 20 -#define TSS_FPR0 16 -#define TSS_FPSCR 12 -#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 152 -#define _LINK 156 -#define _CCR 160 -#define _XER 164 -#define _DAR 168 -#define _DSISR 172 -#define ORIG_GPR3 176 -#define RESULT 180 -#define TRAP 184 diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.1.50/linux/arch/ppc/kernel/ppc_htab.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc_htab.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,196 @@ +/* + * $Id: ppc_htab.c,v 1.4 1997/08/12 04:24:54 cort Exp $ + * PowerPC hash table management proc entry. Will show information + * about the current hash table and will allow changes to it. + * + * 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 +#include +#include +#include + +static long ppc_htab_read(struct inode * inode, struct file * file, + char * buf, unsigned long nbytes); +static long ppc_htab_write(struct inode * inode, struct file * file, + const char * buffer, unsigned long count); +static long long ppc_htab_lseek(struct inode * inode, struct file * file, + long long offset, int orig); + +extern PTE *Hash, *Hash_end; +extern unsigned long Hash_size, Hash_mask; + +static struct file_operations ppc_htab_operations = { + ppc_htab_lseek, /* lseek */ + ppc_htab_read, /* read */ + ppc_htab_write, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL, /* no special release code */ + NULL /* can't fsync */ +}; + +/* + * proc files can do almost nothing.. + */ +struct inode_operations proc_ppc_htab_inode_operations = { + &ppc_htab_operations, /* default proc file-ops */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; + + +/* + * print some useful info about the hash table. This function + * is _REALLY_ slow (see the nested for loops below) but nothing + * in here should be really timing critical. -- Cort + */ +static long ppc_htab_read(struct inode * inode, struct file * file, + char * buf, unsigned long nbytes) +{ + int n = 0, valid; + unsigned int kptes = 0, overflow = 0, uptes = 0; + PTE *ptr; + struct task_struct *p; + + if (nbytes < 0) + return -EINVAL; + + /* + * compute user/kernel pte's table this info can be + * misleading since there can be valid (v bit set) entries + * in the table but their vsid is used by no process (mm->context) + * due to the way tlb invalidation is handled on the ppc + * -- Cort + */ + for ( ptr = Hash ; ptr < (PTE *)(Hash+Hash_size) ; ptr+=sizeof(PTE)) + { + if (ptr->v) + { + /* make sure someone is using this context/vsid */ + for_each_task(p) + { + if ( (ptr->vsid >> 4) == p->mm->context ) + { + valid = 1; + break; + } + } + if ( !valid ) + continue; + /* user not allowed read or write */ + if (ptr->pp == PP_RWXX) + kptes++; + else + uptes++; + if (ptr->h == 1) + overflow++; + } + } + n += sprintf( buf, + "Size\t\t: %luKb\n" + "Buckets\t\t: %lu\n" + "Address\t\t: %08lx\n" + "Entries\t\t: %lu\n" + "User ptes\t: %u\n" + "Kernel ptes\t: %u\n" + "Overflows\t: %u\n" + "Percent full\t: %%%lu\n", + (unsigned long)(Hash_size>>10), + (Hash_size/(sizeof(PTE)*8)), + (unsigned long)Hash, + Hash_size/sizeof(PTE), + uptes, + kptes, + overflow, + ((kptes+uptes)*100) / (Hash_size/sizeof(PTE)) + ); + /* if we're trying to read part of the file that isn't there */ + if ( file->f_pos > n ) + return -ENOMEM; + file->f_pos += n; + return n; +} + +/* + * Can't _yet_ adjust the hash table size while running. -- Cort + */ +static long +ppc_htab_write(struct inode * inode, struct file * file, + const char * buffer, unsigned long count) +{ + if ( current->uid != 0 ) + return -EACCES; + else + return -ENOSYS; + return 0; +} + + +static long long +ppc_htab_lseek(struct inode * inode, struct file * file, + long long offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + return(file->f_pos); + case 1: + file->f_pos += offset; + return(file->f_pos); + case 2: + return(-EINVAL); + default: + return(-EINVAL); + } +} + + +#if 0 +/* + for root.c + */ +static struct proc_dir_entry proc_root_ppc_htab = { + PROC_PPC_HTAB, 8, "ppc_htab", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_ppc_htab_inode_operations +}; +#ifdef __powerpc__ + proc_register(&proc_root, &proc_root_ppc_htab); +#endif + + +/* add to proc_fs.h + PROC_PPC_HTAB,*/ +#endif diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.1.50/linux/arch/ppc/kernel/ppc_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc_ksyms.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void transfer_to_handler(); +void int_return(); +void syscall_trace(); +void do_IRQ(); +void MachineCheckException(); +void AlignmentException(); +void ProgramCheckException(); +void SingleStepException(); +void FloatingPointCheckException(); +void sys_sigreturn(); +extern unsigned lost_interrupts; +extern void do_lost_interrupts(unsigned long); + +EXPORT_SYMBOL(do_signal); +EXPORT_SYMBOL(syscall_trace); +EXPORT_SYMBOL(transfer_to_handler); +EXPORT_SYMBOL(int_return); +EXPORT_SYMBOL(do_IRQ); +EXPORT_SYMBOL(init_task_union); +EXPORT_SYMBOL(MachineCheckException); +EXPORT_SYMBOL(AlignmentException); +EXPORT_SYMBOL(ProgramCheckException); +EXPORT_SYMBOL(SingleStepException); +EXPORT_SYMBOL(sys_sigreturn); +EXPORT_SYMBOL(lost_interrupts); +EXPORT_SYMBOL(do_lost_interrupts); + +EXPORT_SYMBOL(atomic_add); +EXPORT_SYMBOL(atomic_sub); +EXPORT_SYMBOL(atomic_inc); +EXPORT_SYMBOL(atomic_inc_return); +EXPORT_SYMBOL(atomic_dec); +EXPORT_SYMBOL(atomic_dec_return); +EXPORT_SYMBOL(atomic_dec_and_test); + +EXPORT_SYMBOL(set_bit); +EXPORT_SYMBOL(clear_bit); +EXPORT_SYMBOL(change_bit); +EXPORT_SYMBOL(test_and_set_bit); +EXPORT_SYMBOL(test_and_clear_bit); +EXPORT_SYMBOL(test_and_change_bit); +#if 0 +EXPORT_SYMBOL(ffz); +EXPORT_SYMBOL(find_first_zero_bit); +EXPORT_SYMBOL(find_next_zero_bit); +#endif + +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strtok); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(strspn); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memcmp); + +/* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */ +EXPORT_SYMBOL(csum_partial_copy_generic); +EXPORT_SYMBOL(ip_fast_csum); +EXPORT_SYMBOL(csum_tcpudp_magic); + +EXPORT_SYMBOL(__copy_tofrom_user); +EXPORT_SYMBOL(__clear_user); +EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(strlen_user); + +/* +EXPORT_SYMBOL(inb); +EXPORT_SYMBOL(inw); +EXPORT_SYMBOL(inl); +EXPORT_SYMBOL(outb); +EXPORT_SYMBOL(outw); +EXPORT_SYMBOL(outl); +EXPORT_SYMBOL(outsl);*/ + +EXPORT_SYMBOL(_insw); +EXPORT_SYMBOL(_outsw); +EXPORT_SYMBOL(_insl); +EXPORT_SYMBOL(_outsl); +EXPORT_SYMBOL(ioremap); + +EXPORT_SYMBOL(start_thread); + +EXPORT_SYMBOL(__down_interruptible); + +EXPORT_SYMBOL(__cli); +EXPORT_SYMBOL(__sti); +/*EXPORT_SYMBOL(__restore_flags);*/ +EXPORT_SYMBOL(_disable_interrupts); +EXPORT_SYMBOL(_enable_interrupts); +EXPORT_SYMBOL(flush_instruction_cache); +EXPORT_SYMBOL(_get_PVR); +EXPORT_SYMBOL(giveup_fpu); +EXPORT_SYMBOL(flush_icache_range); +EXPORT_SYMBOL(xchg_u32); + +EXPORT_SYMBOL(cuda_request); +EXPORT_SYMBOL(cuda_send_request); +EXPORT_SYMBOL(adb_register); +EXPORT_SYMBOL(abort); +EXPORT_SYMBOL(call_prom); +EXPORT_SYMBOL(find_devices); +EXPORT_SYMBOL(find_type_devices); +EXPORT_SYMBOL(find_path_device); +EXPORT_SYMBOL(get_property); +EXPORT_SYMBOL(pci_io_base); +EXPORT_SYMBOL(pci_device_loc); +EXPORT_SYMBOL(note_scsi_host); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.1.50/linux/arch/ppc/kernel/prep_setup.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/prep_setup.c Sat Aug 16 09:51:08 1997 @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -42,7 +44,7 @@ extern unsigned long loops_per_sec; unsigned long empty_zero_page[1024]; -unsigned char aux_device_present; +extern unsigned char aux_device_present; #ifdef CONFIG_BLK_DEV_RAM extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ @@ -50,19 +52,8 @@ extern int rd_image_start; /* starting block # of image */ #endif -/* copy of the residual data */ -RESIDUAL res; -/* ptr to residual data from hw, must be initialized so not in bss (gets cleared )*/ -unsigned long resptr = 0; -int _machine; -extern unsigned long _TotalMemory; - -#define COMMAND_LINE_SIZE 256 -static char command_line[COMMAND_LINE_SIZE] = { 0, }; -char saved_command_line[COMMAND_LINE_SIZE]; -#ifdef HASHSTATS -unsigned long evicts; -#endif + +extern char saved_command_line[256]; struct screen_info screen_info = { 0, 25, /* orig-x, orig-y */ @@ -76,49 +67,31 @@ 16 /* orig-video-points */ }; -void machine_halt(void) + +/* + * these are here to get by until the pmac/prep merge is done + */ +int pmac_display_supported(char *name) { - machine_restart(NULL); + return 0; } - -void machine_power_off(void) +int sd_find_target(void *a, int b) { - machine_restart(NULL); + return 0; } - -void machine_restart(char *cmd) +void pmac_find_display(void) { - unsigned char ctl; - unsigned long flags; - unsigned long i = 10000; - - _disable_interrupts(); - - /* set exception prefix high - to the prom */ - save_flags( flags ); - restore_flags( flags|MSR_IP ); - - /* make sure bit 0 (reset) is a 0 */ - outb( inb(0x92) & ~1L , 0x92 ); - /* signal a reset to system control port A - soft reset */ - outb( inb(0x92) | 1 , 0x92 ); - - while ( i != 0 ) i++; - panic("restart failed\n"); } int -get_cpuinfo(char *buffer) +prep_get_cpuinfo(char *buffer) { extern char *Motherboard_map_name; + extern RESIDUAL res; int i; int pvr = _get_PVR(); int len; char *model; - PTE *ptr; - unsigned long kptes = 0, uptes = 0, overflow = 0; - unsigned int ti; - switch (pvr>>16) { @@ -226,8 +199,6 @@ /* L2 */ if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */ { - int size; - 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"); @@ -246,61 +217,25 @@ * Ooh's and aah's info about zero'd pages in idle task */ { - extern unsigned int zerocount, zerototal, zeropage_hits; + extern unsigned int zerocount, zerototal, zeropage_hits,zeropage_calls; len += sprintf(buffer+len,"zero pages\t: total %u (%uKb) " - "current: %u (%uKb) hits: %u\n", + "current: %u (%uKb) hits: %u/%u (%lu%%)\n", zerototal, (zerototal*PAGE_SIZE)>>10, zerocount, (zerocount*PAGE_SIZE)>>10, - zeropage_hits); - } - - - /* ram/hash table info */ - len += sprintf(buffer+len,"hash table\t: %dkB (%dk buckets)\n", - Hash_size>>10,(Hash_size/(sizeof(PTE)*8)) >> 10); - - /* if booted print info about hash table use (overflows, etc) */ -#ifdef HASHSTATS - for ( ptr = Hash ; ptr < (PTE *)(Hash+Hash_size) ; ptr++) - { - if (ptr->v) - { - /* user not allowed read or write */ - if (ptr->pp == PP_RWXX) - kptes++; - else - uptes++; - if (ptr->h == 1) - overflow++; - } + zeropage_hits,zeropage_calls, + /* : 1 below is so we don't div by zero */ + (zeropage_hits*100) / + ((zeropage_calls)?zeropage_calls:1)); } - /*len+=sprintf(buffer+len,"Hash %x Hash+Hash_size %x MemEnd %x\n", - Hash,Hash+Hash_size,KERNELBASE+_TotalMemory);*/ - /*len += sprintf(buffer+len,"PTEs: (user/kernel/max) %d (%d%%)/%d " - "(%d%%)/%d (%d%% full)\n", - uptes,(uptes*100)/(Hash_size/sizeof(PTE)), - kptes,(kptes*100)/(Hash_size/sizeof(PTE)), - Hash_size/sizeof(PTE), - ((uptes+kptes)*100)/(Hash_size/sizeof(PTE))); - len += sprintf(buffer+len,"Current Ovflw PTE's: %d Total Evicts: %u\n", - overflow,evicts);*/ -#endif /* HASHSTATS */ return len; } -__initfunc(unsigned long -bios32_init(unsigned long memory_start, unsigned long memory_end)) -{ - return memory_start; -} - __initfunc(void -setup_arch(char **cmdline_p, unsigned long * memory_start_p, +prep_setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { extern char cmd_line[]; extern char _etext[], _edata[], _end[]; - unsigned char reg; extern int panic_timeout; /* Save unparsed command line copy for /proc/cmdline */ @@ -308,13 +243,13 @@ *cmdline_p = cmd_line; *memory_start_p = (unsigned long) Hash+Hash_size; - (unsigned long *)*memory_end_p = (unsigned long *)(_TotalMemory+KERNELBASE); + (unsigned long *)*memory_end_p = (unsigned long *)(res.TotalMemory+KERNELBASE); /* init to some ~sane value until calibrate_delay() runs */ loops_per_sec = 50000000; /* reboot on panic */ - /*panic_timeout = 180;*/ + panic_timeout = 180; init_task.mm->start_code = PAGE_OFFSET; init_task.mm->end_code = (unsigned long) _etext; @@ -332,23 +267,7 @@ ROOT_DEV = to_kdev_t(0x0801); /* sda1 */ break; } - /*ROOT_DEV = to_kdev_t(0x0811);*/ /* sdb1 */ -#if 0 - strcpy(cmd_line+strlen(cmd_line),"console=1,9600,n8"); -#endif -#if 0 - if ( _machine == _MACH_Motorola ) - { - /* get root via nfs from gordito -- only used for testing */ - ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); /* nfs */ - /*nfsaddrs=myip:serverip:gateip:netmaskip:clientname*/ - strcpy(cmd_line+strlen(cmd_line), - "nfsaddrs=129.138.6.13:129.138.6.101:129.138.6.1:255.255.255.0:" - "pandora nfsroot=/usr/src/root/"); - } -#endif - #ifdef CONFIG_BLK_DEV_RAM #if 0 ROOT_DEV = to_kdev_t(0x0200); /* floppy */ @@ -356,7 +275,20 @@ rd_doload = 1; rd_image_start = 0; #endif + /* initrd_start and size are setup by boot/head.S and kernel/head.S */ + if ( initrd_start ) + { + if (initrd_end > *memory_end_p) + { + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + initrd_end,*memory_end_p); + initrd_start = 0; + } + } #endif + + printk("Boot arguments: %s\n", cmd_line); request_region(0x20,0x20,"pic1"); request_region(0xa0,0x20,"pic2"); @@ -365,4 +297,3 @@ request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); } - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c --- v2.1.50/linux/arch/ppc/kernel/prep_time.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/prep_time.c Sat Aug 16 09:51:08 1997 @@ -23,18 +23,72 @@ #include #include #include +#include -/* last time the cmos clock got updated */ -static long last_rtc_update = 0; -static int set_rtc_mmss(unsigned long nowtime); -unsigned long get_cmos_time(void); -static inline unsigned long mktime(unsigned int, unsigned int,unsigned int, +#include "time.h" + +inline unsigned long mktime(unsigned int, unsigned int,unsigned int, unsigned int, unsigned int, unsigned int); -#define TIMER_IRQ 0 -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned long long last_timer_cc = 0; -static unsigned long long init_timer_cc = 0; +/* + * The motorola uses the m48t18 rtc (includes DS1643) whose registers + * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818 + * rtc (ds1386) which has regs at addr 0-d). The intel gets + * past this because the bios emulates the mc146818. + * + * Why in the world did they have to use different clocks? + * + * Right now things are hacked to check which machine we're on then + * use the appropriate macro. This is very very ugly and I should + * probably have a function that checks which machine we're on then + * does things correctly transparently or a function pointer which + * is setup at boot time to use the correct addresses. + * -- Cort + */ +/* + * translate from mc146818 to m48t18 addresses + */ +unsigned int clock_transl[] = { MOTO_RTC_SECONDS,0 /* alarm */, + MOTO_RTC_MINUTES,0 /* alarm */, + MOTO_RTC_HOURS,0 /* alarm */, /* 4,5 */ + MOTO_RTC_DAY_OF_WEEK, + MOTO_RTC_DAY_OF_MONTH, + MOTO_RTC_MONTH, + MOTO_RTC_YEAR, /* 9 */ + MOTO_RTC_CONTROLA, MOTO_RTC_CONTROLB /* 10,11 */ +}; + +int prep_cmos_clock_read(int addr) +{ + if ( _machine == _MACH_IBM ) + return CMOS_READ(addr); + else if ( _machine == _MACH_Motorola ) + { + outb(clock_transl[addr]>>8, NVRAM_AS1); + outb(clock_transl[addr], NVRAM_AS0); + return (inb(NVRAM_DATA)); + } + + printk("Unknown machine in prep_cmos_clock_read()!\n"); + return -1; +} + +void prep_cmos_clock_write(unsigned long val, int addr) +{ + if ( _machine == _MACH_IBM ) + { + CMOS_WRITE(val,addr); + return; + } + else if ( _machine == _MACH_Motorola ) + { + outb(clock_transl[addr]>>8, NVRAM_AS1); + outb(clock_transl[addr], NVRAM_AS0); + outb(val,NVRAM_DATA); + return; + } + printk("Unknown machine in prep_cmos_clock_write()!\n"); +} #define TICK_SIZE tick #define FEBRUARY 2 @@ -49,6 +103,7 @@ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +#if 0 static unsigned long do_slow_gettimeoffset(void) { int count; @@ -69,7 +124,6 @@ count = (count + LATCH/2) / LATCH; return offset + count; } - static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; /* @@ -106,6 +160,8 @@ sti(); } +#endif + void to_tm(int tim, struct rtc_time * tm) { register int i; @@ -139,20 +195,20 @@ /* * Set the hardware clock. -- Cort */ -static int set_rtc_mmss(unsigned long nowtime) +int prep_set_rtc_time(unsigned long nowtime) { - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; struct rtc_time tm; to_tm(nowtime, &tm); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + save_control = prep_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */ - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + prep_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = prep_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */ + + prep_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); tm.tm_year -= 1900; if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { @@ -163,12 +219,12 @@ BIN_TO_BCD(tm.tm_mday); BIN_TO_BCD(tm.tm_year); } - CMOS_WRITE(tm.tm_sec,RTC_SECONDS); - CMOS_WRITE(tm.tm_min,RTC_MINUTES); - CMOS_WRITE(tm.tm_hour,RTC_HOURS); - CMOS_WRITE(tm.tm_mon,RTC_MONTH); - CMOS_WRITE(tm.tm_mday,RTC_DAY_OF_MONTH); - CMOS_WRITE(tm.tm_year,RTC_YEAR); + prep_cmos_clock_write(tm.tm_sec,RTC_SECONDS); + prep_cmos_clock_write(tm.tm_min,RTC_MINUTES); + prep_cmos_clock_write(tm.tm_hour,RTC_HOURS); + prep_cmos_clock_write(tm.tm_mon,RTC_MONTH); + prep_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH); + prep_cmos_clock_write(tm.tm_year,RTC_YEAR); /* The following flags have to be released exactly in this order, * otherwise the DS12887 (popular MC146818A clone with integrated @@ -177,15 +233,15 @@ * the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + prep_cmos_clock_write(save_control, RTC_CONTROL); + prep_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT); if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) ) time_state = TIME_OK; return 0; } -unsigned long get_cmos_time(void) +unsigned long prep_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; int i; @@ -197,20 +253,20 @@ */ /* read RTC exactly on falling edge of update flag */ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + if (prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP) break; for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + if (!(prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)) break; do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + sec = prep_cmos_clock_read(RTC_SECONDS); + min = prep_cmos_clock_read(RTC_MINUTES); + hour = prep_cmos_clock_read(RTC_HOURS); + day = prep_cmos_clock_read(RTC_DAY_OF_MONTH); + mon = prep_cmos_clock_read(RTC_MONTH); + year = prep_cmos_clock_read(RTC_YEAR); + } while (sec != prep_cmos_clock_read(RTC_SECONDS)); + if (!(prep_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); BCD_TO_BIN(min); @@ -224,19 +280,68 @@ return mktime(year, mon, day, hour, min, sec); } +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +inline unsigned long mktime(unsigned int year, unsigned int mon, + unsigned int day, unsigned int hour, + unsigned int min, unsigned int sec) +{ + + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + return ((( + (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) + + year*365 - 719499 + )*24 + hour /* now have hours */ + )*60 + min /* now have minutes */ + )*60 + sec; /* finally seconds */ +} + +#if 0 +void time_init(void) +{ + void (*irq_handler)(int, void *,struct pt_regs *); + + xtime.tv_sec = prep_get_rtc_time(); + xtime.tv_usec = 0; + + prep_calibrate_decr(); + + /* If we have the CPU hardware time counters, use them */ + irq_handler = timer_interrupt; + if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) + panic("Could not allocate timer IRQ!"); +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ static inline void timer_interrupt(int irq, void *dev, struct pt_regs * regs) { + prep_calibrate_decr_handler(irq,dev,regs); do_timer(regs); /* update the hw clock if: * the time is marked out of sync (TIME_ERROR) * or ~11 minutes have expired since the last update -- Cort * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * CMOS clock accordingly every ~11 minutes. prep_set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ if ( time_state == TIME_BAD || @@ -244,7 +349,7 @@ /*if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && xtime.tv_usec > 500000 - (tick >> 1) && xtime.tv_usec < 500000 + (tick >> 1))*/ - if (set_rtc_mmss(xtime.tv_sec) == 0) + if (prep_set_rtc_time(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ @@ -269,47 +374,4 @@ } #endif } - - -/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. - * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 - * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. - * - * [For the Julian calendar (which was used in Russia before 1917, - * Britain & colonies before 1752, anywhere else before 1582, - * and is still in use by some communities) leave out the - * -year/100+year/400 terms, and add 10.] - * - * This algorithm was first published by Gauss (I think). - * - * WARNING: this function will overflow on 2106-02-07 06:28:16 on - * machines were long is 32-bit! (However, as time_t is signed, we - * will already get problems at other places on 2038-01-19 03:14:08) - */ -static inline unsigned long mktime(unsigned int year, unsigned int mon, - unsigned int day, unsigned int hour, - unsigned int min, unsigned int sec) -{ - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ - mon += 12; /* Puts Feb last since it has leap day */ - year -= 1; - } - return ((( - (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) + - year*365 - 719499 - )*24 + hour /* now have hours */ - )*60 + min /* now have minutes */ - )*60 + sec; /* finally seconds */ -} - -void time_init(void) -{ - void (*irq_handler)(int, void *,struct pt_regs *); - xtime.tv_sec = get_cmos_time(); - xtime.tv_usec = 0; - - /* If we have the CPU hardware time counters, use them */ - irq_handler = timer_interrupt; - if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) - panic("Could not allocate timer IRQ!"); -} +#endif diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.1.50/linux/arch/ppc/kernel/process.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/process.c Sat Aug 16 09:51:08 1997 @@ -7,7 +7,7 @@ * Derived from "arch/i386/kernel/process.c" * Copyright (C) 1995 Linus Torvalds * - * Modified by Cort Dougan (cort@cs.nmt.edu) and + * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and * Paul Mackerras (paulus@cs.anu.edu.au) * * This program is free software; you can redistribute it and/or @@ -28,22 +28,22 @@ #include #include #include -#include +#include #include +#include #include #include #include #include #include +#include -int dump_fpu(void); +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs); void switch_to(struct task_struct *, struct task_struct *); -void print_backtrace(unsigned long *); -void show_regs(struct pt_regs * regs); -void inline zero_paged(void); extern unsigned long _get_SP(void); + #undef SHOW_TASK_SWITCHES 1 #undef CHECK_STACK 1 #undef IDLE_ZERO 1 @@ -59,7 +59,7 @@ { return ((unsigned long)tsk) + sizeof(struct task_struct); } - + static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; @@ -69,9 +69,12 @@ union task_union init_task_union = { INIT_TASK }; int -dump_fpu(void) +dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) { - return (1); + if (last_task_used_math == current) + giveup_fpu(); + memcpy(fpregs, ¤t->tss.fpr[0], sizeof(*fpregs)); + return 1; } /* check to make sure the kernel stack is healthy */ @@ -80,7 +83,6 @@ unsigned long stack_top = kernel_stack_top(tsk); unsigned long tsk_top = task_top(tsk); int ret = 0; - unsigned long *i; #if 0 /* check tss magic */ @@ -98,7 +100,7 @@ if ( (tsk->tss.ksp > stack_top) || (tsk->tss.ksp < tsk_top) ) { printk("stack out of bounds: %s/%d\n" - " tsk_top %08x ksp %08x stack_top %08x\n", + " tsk_top %08lx ksp %08lx stack_top %08lx\n", tsk->comm,tsk->pid, tsk_top, tsk->tss.ksp, stack_top); ret |= 2; @@ -108,7 +110,7 @@ if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) ) { printk("current stack ptr out of bounds: %s/%d\n" - " tsk_top %08x sp %08x stack_top %08x\n", + " tsk_top %08lx sp %08lx stack_top %08lx\n", current->comm,current->pid, tsk_top, _get_SP(), stack_top); ret |= 4; @@ -143,15 +145,12 @@ { struct thread_struct *new_tss, *old_tss; int s = _disable_interrupts(); - struct pt_regs *regs = (struct pt_regs *)(new->tss.ksp+STACK_FRAME_OVERHEAD); #if CHECK_STACK check_stack(prev); check_stack(new); #endif - /* turn off fpu for task last to run */ - /*prev->tss.regs->msr &= ~MSR_FP;*/ - + #ifdef SHOW_TASK_SWITCHES printk("%s/%d (%x) -> %s/%d (%x) ctx %x\n", prev->comm,prev->pid,prev->tss.regs->nip, @@ -160,289 +159,29 @@ new_tss = &new->tss; old_tss = ¤t->tss; _switch(old_tss, new_tss, new->mm->context); - /* turn off fpu for task last to run */ _enable_interrupts(s); } - -#include -asmlinkage int sys_debug(long a, long b, long c, long d, long e, long f,struct pt_regs *regs) -{ -#if 1 - struct task_struct *p; - printk("sys_debug(): r3 %x r4 %x r5 %x r6 %x\n", a,b,c,d); - printk("last %x\n", last_task_used_math); - printk("cur %x regs %x/%x tss %x/%x\n", - current, current->tss.regs,regs,¤t->tss,current->tss); - for_each_task(p) - { - if ((long)p < KERNELBASE) - { - printk("nip %x lr %x r3 %x\n", regs->nip,regs->link,a); - print_mm_info(); - __cli(); - while(1); - } - } - return regs->gpr[3]; -#endif -#if 0 - /* set the time in the cmos clock */ - unsigned long hwtime, nowtime; - struct rtc_time tm; - - hwtime = get_cmos_time(); - to_tm(hwtime, &tm); - printk("hw: H:M:S M/D/Y %02d:%02d:%02d %d/%d/%d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mon, - tm.tm_mday, tm.tm_year); - return; -#endif -} -/* - * vars for idle task zero'ing out pages - */ -unsigned long zero_list = 0; /* head linked list of pre-zero'd pages */ -unsigned long bytecount = 0; /* pointer into the currently being zero'd page */ -unsigned long zerocount = 0; /* # currently pre-zero'd pages */ -unsigned long zerototal = 0; /* # pages zero'd over time -- for ooh's and ahhh's */ -unsigned long pageptr = 0; /* current page being zero'd */ -unsigned long zeropage_hits = 0;/* # zero'd pages request that we've done */ - -/* - * Returns a pre-zero'd page from the list otherwise returns - * NULL. - */ -unsigned long get_prezerod_page(void) +asmlinkage int sys_debug(long a, long b, long c, long d, long e, long f,struct pt_regs *regs) { - unsigned long page; - unsigned long s; - - if ( zero_list ) - { - /* atomically remove this page from the list */ - asm ( "101:lwarx %1,0,%2\n" /* reserve zero_list */ - " lwz %0,0(%1)\n" /* get next -- new zero_list */ - " stwcx. %0,0,%2\n" /* update zero_list */ - " bne- 101b\n" /* if lost reservation try again */ - : "=&r" (zero_list), "=&r" (page) - : "r" (&zero_list) - : "cc" ); - /* we can update zerocount after the fact since it is not - * used for anything but control of a loop which doesn't - * matter since it won't effect anything if it zero's one - * less page -- Cort - */ - atomic_inc((atomic_t *)&zeropage_hits); - atomic_dec((atomic_t *)&zerocount); - /* zero out the pointer to next in the page */ - *(unsigned long *)page = 0; - return page; - } return 0; } -/* - * Experimental stuff to zero out pages in the idle task - * to speed up get_free_pages() -- Cort - * Zero's out pages until we need to resched or - * we've reached the limit of zero'd pages. - */ -void inline zero_paged(void) -{ - extern pte_t *get_pte( struct mm_struct *mm, unsigned long address ); - unsigned long tmp; - pte_t ptep; - pgd_t *dir; - pmd_t *pmd; - pte_t *pte; - - sprintf(current->comm, "zero_paged"); - printk("Started zero_paged\n"); - /* want priority over idle task and powerd */ - current->priority = -98; - current->counter = -98; - __sti(); - - while ( zerocount < 128 ) - { - /* - * Mark a page as reserved so we can mess with it - * If we're interrupted we keep this page and our place in it - * since we validly hold it and it's reserved for us. - */ - pageptr = __get_free_pages(GFP_ATOMIC, 0, 0 ); - if ( !pageptr ) - { - printk("!pageptr in zero_paged\n"); - goto retry; - } - - if ( need_resched ) - schedule(); - - /* - * Make the page no cache so we don't blow our cache with 0's - */ - dir = pgd_offset( init_task.mm, pageptr ); - if (dir) - { - pmd = pmd_offset(dir, pageptr & PAGE_MASK); - if (pmd && pmd_present(*pmd)) - { - pte = pte_offset(pmd, pageptr & PAGE_MASK); - if (pte && pte_present(*pte)) - { - pte_uncache(*pte); - flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); - } - } - } - - /* - * Important here to not take time away from real processes. - */ - for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 ) - { - if ( need_resched ) - schedule(); - *(unsigned long *)(bytecount + pageptr) = 0; - } - - /* - * If we finished zero-ing out a page add this page to - * the zero_list atomically -- we can't use - * down/up since we can't sleep in idle. - * Disabling interrupts is also a bad idea since we would - * steal time away from real processes. - * We can also have several zero_paged's running - * on different processors so we can't interfere with them. - * So we update the list atomically without locking it. - * -- Cort - */ - /* turn cache on for this page */ - pte_cache(*pte); - flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr); - - /* atomically add this page to the list */ - asm ( "101:lwarx %0,0,%1\n" /* reserve zero_list */ - " stw %0,0(%2)\n" /* update *pageptr */ -#ifdef __SMP__ - " sync\n" /* let store settle */ -#endif - " mr %0,%2\n" /* update zero_list in reg */ - " stwcx. %2,0,%1\n" /* update zero_list in mem */ - " bne- 101b\n" /* if lost reservation try again */ - : "=&r" (zero_list) - : "r" (&zero_list), "r" (pageptr) - : "cc" ); - /* - * This variable is used in the above loop and nowhere - * else so the worst that could happen is we would - * zero out one more or one less page than we want - * per processor on the machine. This is because - * we could add our page to the list but not have - * zerocount updated yet when another processor - * reads it. -- Cort - */ - atomic_inc((atomic_t *)&zerocount); - atomic_inc((atomic_t *)&zerototal); -retry: - schedule(); - } -} - -void powerd(void) -{ - unsigned long msr, hid0; - - sprintf(current->comm, "powerd"); - __sti(); - while (1) - { - /* want priority over idle task 'swapper' -- Cort */ - current->priority = -99; - current->counter = -99; - asm volatile( - /* clear powersaving modes and set nap mode */ - "mfspr %3,1008 \n\t" - "andc %3,%3,%4 \n\t" - "or %3,%3,%5 \n\t" - "mtspr 1008,%3 \n\t" - /* enter the mode */ - "mfmsr %0 \n\t" - "oris %0,%0,%2 \n\t" - "sync \n\t" - "mtmsr %0 \n\t" - "isync \n\t" - : "=&r" (msr) - : "0" (msr), "i" (MSR_POW>>16), - "r" (hid0), - "r" (HID0_DOZE|HID0_NAP|HID0_SLEEP), - "r" (HID0_NAP)); - if ( need_resched ) - schedule(); - /* - * The ibm carolina spec says that the eagle memory - * controller will detect the need for a snoop - * and wake up the processor so we don't need to - * check for cache operations that need to be - * snooped. The ppc book says the run signal - * must be asserted while napping for this though. - * -- Cort - */ - } -} - -asmlinkage int sys_idle(void) -{ - int ret = -EPERM; - if (current->pid != 0) - goto out; - -#ifdef IDLE_ZERO - /* - * want one per cpu since it would be nice to have all - * processors who aren't doing anything - * zero-ing pages since this daemon is lock-free - * -- Cort - */ - kernel_thread(zero_paged, NULL, 0); -#endif /* IDLE_ZERO */ - -#ifdef CONFIG_POWERSAVING - /* no powersaving modes on 601 - one per processor */ - if( (_get_PVR()>>16) != 1 ) - kernel_thread(powerd, NULL, 0); -#endif /* CONFIG_POWERSAVING */ - - /* endless loop with no priority at all */ - current->priority = -100; - current->counter = -100; - for (;;) - { - schedule(); - } - ret = 0; -out: - return ret; -} - void show_regs(struct pt_regs * regs) { int i; - printk("NIP: %08X XER: %08X LR: %08X REGS: %08X TRAP: %04x\n", + printk("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx\n", regs->nip, regs->xer, regs->link, regs,regs->trap); - printk("MSR: %08x EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", + printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, regs->msr&MSR_IR ? 1 : 0, regs->msr&MSR_DR ? 1 : 0); - printk("TASK = %x[%d] '%s' mm->pgd %08X ", + printk("TASK = %p[%d] '%s' mm->pgd %p ", current, current->pid, current->comm, current->mm->pgd); - printk("Last syscall: %d ", current->tss.last_syscall); - printk("\nlast math %08X\n", last_task_used_math); + printk("Last syscall: %ld ", current->tss.last_syscall); + printk("\nlast math %p\n", last_task_used_math); for (i = 0; i < 32; i++) { long r; @@ -451,9 +190,9 @@ printk("GPR%02d: ", i); } - if ( get_user(r, &(regs->gpr[i])) ) + if ( __get_user(r, &(regs->gpr[i])) ) goto out; - printk("%08X ", r); + printk("%08lX ", r); if ((i % 8) == 7) { printk("\n"); @@ -480,14 +219,14 @@ } /* - * Copy a thread.. - */ + * Copy a thread.. + */ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { - int i; struct pt_regs * childregs; + /* Copy registers */ childregs = ((struct pt_regs *) ((unsigned long)p + sizeof(union task_union) @@ -497,13 +236,13 @@ if ((childregs->msr & MSR_PR) == 0) childregs->gpr[2] = (unsigned long) p; /* `current' in new task */ childregs->gpr[3] = 0; /* Result from fork() */ - p->tss.ksp = (unsigned long)(childregs) - STACK_FRAME_OVERHEAD; - p->tss.regs = (struct pt_regs *)(childregs); - if (usp >= (unsigned long)regs) - { /* Stack is in kernel space - must adjust */ - childregs->gpr[1] = (long)(childregs+1); - } else - { /* Provided stack is in user space */ + p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD; + p->tss.regs = childregs; + if (usp >= (unsigned long) regs) { + /* Stack is in kernel space - must adjust */ + childregs->gpr[1] = (unsigned long)(childregs + 1); + } else { + /* Provided stack is in user space */ childregs->gpr[1] = usp; } @@ -511,24 +250,75 @@ /* * copy fpu info - assume lazy fpu switch now always - * this should really be conditional on whether or - * not the process has used the fpu * -- Cort */ if ( last_task_used_math == current ) giveup_fpu(); - + memcpy(&p->tss.fpr, ¤t->tss.fpr, sizeof(p->tss.fpr)); p->tss.fpscr = current->tss.fpscr; childregs->msr &= ~MSR_FP; - + return 0; } +/* + * XXX ld.so expects the auxiliary table to start on + * a 16-byte boundary, so we have to find it and + * move it up. :-( + */ +static inline void shove_aux_table(unsigned long sp) +{ + int argc; + char *p; + unsigned long e; + unsigned long aux_start, offset; + + if (__get_user(argc, (int *)sp)) + return; + sp += sizeof(int) + (argc + 1) * sizeof(char *); + /* skip over the environment pointers */ + do { + if (__get_user(p, (char **)sp)) + return; + sp += sizeof(char *); + } while (p != NULL); + aux_start = sp; + /* skip to the end of the auxiliary table */ + do { + if (__get_user(e, (unsigned long *)sp)) + return; + sp += 2 * sizeof(unsigned long); + } while (e != AT_NULL); + offset = ((aux_start + 15) & ~15) - aux_start; + if (offset != 0) { + do { + sp -= sizeof(unsigned long); + if (__get_user(e, (unsigned long *)sp) + || __put_user(e, (unsigned long *)(sp + offset))) + return; + } while (sp > aux_start); + } +} + +/* + * Set up a thread for executing a new program + */ +void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) +{ + set_fs(USER_DS); + regs->nip = nip; + regs->gpr[1] = sp; + regs->msr = MSR_USER; + shove_aux_table(sp); +} + + asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { int ret; + lock_kernel(); ret = do_fork(SIGCHLD, regs->gpr[1], regs); unlock_kernel(); @@ -541,26 +331,26 @@ { int error; char * filename; - filename = (int) getname((char *) a0); + + filename = getname((char *) a0); error = PTR_ERR(filename); - if(IS_ERR(filename)) + if (IS_ERR(filename)) goto out; if ( last_task_used_math == current ) last_task_used_math = NULL; error = do_execve(filename, (char **) a1, (char **) a2, regs); - putname(filename); - out: unlock_kernel(); return error; } -asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) +asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, + struct pt_regs *regs) { unsigned long clone_flags = p1; int res; - + lock_kernel(); res = do_fork(clone_flags, regs->gpr[1], regs); unlock_kernel(); @@ -571,34 +361,23 @@ print_backtrace(unsigned long *sp) { int cnt = 0; - int i; + unsigned long i; + printk("Call backtrace: "); - while ( !get_user(i, sp) && i) - { - if ( get_user( i, &sp[1] ) ) - return; - printk("%08X ", i); - if ( get_user( (ulong)sp, sp) ) - return; - if (cnt == 6 ) cnt = 7; /* wraparound early -- Cort */ - if (++cnt == 8) - { + while (sp) { + if (__get_user( i, &sp[1] )) + break; + if (cnt++ % 7 == 0) printk("\n"); - } + printk("%08lX ", i); if (cnt > 32) break; + if (__get_user(sp, (unsigned long **)sp)) + break; } printk("\n"); } -inline void start_thread(struct pt_regs * regs, - unsigned long eip, unsigned long esp) -{ - set_fs(USER_DS); - regs->nip = eip; - regs->gpr[1] = esp; - regs->msr = MSR_USER; -} - +#if 0 /* * Low level print for debugging - Cort */ @@ -651,3 +430,4 @@ orig_x = x; orig_y = y; } +#endif /* CONFIG_PREP */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.1.50/linux/arch/ppc/kernel/prom.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/prom.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,523 @@ +/* + * Procedures for interfacing to the Open Firmware PROM on + * Power Macintosh computers. + * + * In particular, we are interested in the device tree + * and in using some of its services (exit, write to stdout). + * + * Paul Mackerras August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define getpromprop(node, name, buf, len) \ + ((int)call_prom("getprop", 4, 1, (node), (name), (buf), (len))) + +ihandle prom_stdout; +ihandle prom_chosen; + +char command_line[256]; +int screen_initialized = 0; + +char prom_display_path[128]; + +struct prom_args { + const char *service; + int nargs; + int nret; + void *args[10]; +} prom_args; + +struct pci_address { + unsigned a_hi; + unsigned a_mid; + unsigned a_lo; +}; + +struct pci_reg_property { + struct pci_address addr; + unsigned size_hi; + unsigned size_lo; +}; + +struct pci_range { + struct pci_address addr; + unsigned phys; + unsigned size_hi; + unsigned size_lo; +}; + +void (*prom_entry)(void *); +extern int prom_trashed; + +static int prom_callback(struct prom_args *); +static unsigned long inspect_node(phandle, struct device_node *, unsigned long, + unsigned long, unsigned long); +static void check_display(void); +static int prom_next_node(phandle *); + +extern int pmac_display_supported(const char *); +extern void enter_prom(void *); + +void +prom_exit() +{ + struct prom_args args; + + args.service = "exit"; + args.nargs = 0; + args.nret = 0; + enter_prom(&args); + for (;;) /* should never get here */ + ; +} + +void * +call_prom(const char *service, int nargs, int nret, ...) +{ + va_list list; + int i; + + if (prom_trashed) + panic("prom called after its memory was reclaimed"); + prom_args.service = service; + prom_args.nargs = nargs; + prom_args.nret = nret; + va_start(list, nret); + for (i = 0; i < nargs; ++i) + prom_args.args[i] = va_arg(list, void *); + va_end(list); + for (i = 0; i < nret; ++i) + prom_args.args[i + nargs] = 0; + enter_prom(&prom_args); + return prom_args.args[nargs]; +} + +void +prom_print(const char *msg) +{ + const char *p, *q; + const char *crlf = "\r\n"; + + if (screen_initialized) + return; + for (p = msg; *p != 0; p = q) { + for (q = p; *q != 0 && *q != '\n'; ++q) + ; + if (q > p) + call_prom("write", 3, 1, prom_stdout, p, q - p); + if (*q != 0) { + ++q; + call_prom("write", 3, 1, prom_stdout, crlf, 2); + } + } +} + +/* + * We enter here early on, when the Open Firmware prom is still + * handling exceptions and the MMU hash table for us. + */ +void +prom_init(char *params, int unused, void (*pp)(void *)) +{ + /* First get a handle for the stdout device */ + if ( _machine != _MACH_Pmac ) /* prep */ + return; + prom_entry = pp; + prom_chosen = call_prom("finddevice", 1, 1, "/chosen"); + if (prom_chosen == (void *)-1) + prom_exit(); + call_prom("getprop", 4, 1, prom_chosen, "stdout", &prom_stdout, + (void *) sizeof(prom_stdout)); + + /* + * If we were booted via quik, params points to the physical address + * of the command-line parameters. + * If we were booted from an xcoff image (i.e. netbooted or + * booted from floppy), we get the command line from the bootargs + * property of the /chosen node. If an initial ramdisk is present, + * params and unused are used for initrd_start and initrd_size, + * otherwise they contain 0xdeadbeef. + */ + command_line[0] = 0; + if ((unsigned long) params >= 0x4000 + && (unsigned long) params < 0x800000 + && unused == 0) { + strncpy(command_line, params+KERNELBASE, sizeof(command_line)); + } else { +#ifdef CONFIG_BLK_DEV_INITRD + if ((unsigned long) params - KERNELBASE < 0x800000 + && unused != 0 && unused != 0xdeadbeef) { + initrd_start = (unsigned long) params; + initrd_end = initrd_start + unused; + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + } +#endif + call_prom("getprop", 4, 1, prom_chosen, "bootargs", + command_line, sizeof(command_line)); + } + command_line[sizeof(command_line) - 1] = 0; + + check_display(); +} + +/* + * If we have a display that we don't know how to drive, + * we will want to try to execute OF's open method for it + * later. However, OF may fall over if we do that after + * we've taken over the MMU and done set_prom_callback. + * So we check whether we will need to open the display, + * and if so, open it now. + */ +static void +check_display() +{ + phandle node; + ihandle ih; + char type[16], name[64], path[128]; + + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + getpromprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + continue; + name[0] = 0; + getpromprop(node, "name", name, sizeof(name)); + if (pmac_display_supported(name)) + /* we have a supported display */ + return; + } + printk(KERN_INFO "No supported display found\n"); + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + getpromprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + continue; + /* It seems OF doesn't null-terminate the path :-( */ + memset(path, 0, sizeof(path)); + if ((int) call_prom("package-to-path", 3, 1, + node, path, sizeof(path) - 1) < 0) { + printk(KERN_WARNING "can't get path for display %p\n", + node); + continue; + } + ih = call_prom("open", 1, 1, path); + if (ih == 0 || ih == (ihandle) -1) { + printk(KERN_WARNING "couldn't open display %s\n", + path); + continue; + } + printk(KERN_INFO "Opened display device %s using " + "Open Firmware\n", path); + strcpy(prom_display_path, path); + break; + } +} + +static int +prom_next_node(phandle *nodep) +{ + phandle node; + + if ((node = *nodep) != 0 + && (*nodep = call_prom("child", 1, 1, node)) != 0) + return 1; + if ((*nodep = call_prom("peer", 1, 1, node)) != 0) + return 1; + for (;;) { + if ((node = call_prom("parent", 1, 1, node)) == 0) + return 0; + if ((*nodep = call_prom("peer", 1, 1, node)) != 0) + return 1; + } +} + +/* + * Callback routine for the PROM to call us. + * No services are implemented yet :-) + */ +static int +prom_callback(struct prom_args *argv) +{ + printk("uh oh, prom callback '%s' (%d/%d)\n", argv->service, + argv->nargs, argv->nret); + return -1; +} + +/* + * Register a callback with the Open Firmware PROM so it can ask + * us to map/unmap memory, etc. + */ +void +set_prom_callback() +{ + call_prom("set-callback", 1, 1, prom_callback); +} + +void +abort() +{ +#ifdef CONFIG_XMON + xmon(0); +#endif + prom_exit(); +} + +/* + * Make a copy of the device tree from the PROM. + */ + +static struct device_node *allnodes; +static struct device_node **allnextp; + +#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) + +unsigned long +copy_device_tree(unsigned long mem_start, unsigned long mem_end) +{ + phandle root; + + root = call_prom("peer", 1, 1, (phandle)0); + if (root == (phandle)0) + panic("couldn't get device tree root\n"); + allnextp = &allnodes; + mem_start = inspect_node(root, 0, 0, mem_start, mem_end); + *allnextp = 0; + return mem_start; +} + +static unsigned long +inspect_node(phandle node, struct device_node *dad, unsigned long base_address, + unsigned long mem_start, unsigned long mem_end) +{ + struct reg_property *reg, *rp; + struct pci_reg_property *pci_addrs; + int l, i; + phandle child; + struct device_node *np; + struct property *pp, **prev_propp; + char *prev_name; + + np = (struct device_node *) mem_start; + mem_start += sizeof(struct device_node); + memset(np, 0, sizeof(*np)); + np->node = node; + *allnextp = np; + allnextp = &np->allnext; + np->parent = dad; + if (dad != 0) { + /* we temporarily use the `next' field as `last_child'. */ + if (dad->next == 0) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + + /* get and store all properties */ + prev_propp = &np->properties; + prev_name = 0; + for (;;) { + pp = (struct property *) mem_start; + pp->name = (char *) (pp + 1); + if ((int) call_prom("nextprop", 3, 1, node, prev_name, + pp->name) <= 0) + break; + mem_start = ALIGN((unsigned long)pp->name + + strlen(pp->name) + 1); + pp->value = (unsigned char *) mem_start; + pp->length = (int) + call_prom("getprop", 4, 1, node, pp->name, pp->value, + mem_end - mem_start); + if (pp->length < 0) + panic("hey, where did property %s go?", pp->name); + mem_start = ALIGN(mem_start + pp->length); + prev_name = pp->name; + *prev_propp = pp; + prev_propp = &pp->next; + } + *prev_propp = 0; + + np->name = get_property(np, "name", 0); + np->type = get_property(np, "device_type", 0); + + /* get all the device addresses and interrupts */ + reg = (struct reg_property *) mem_start; + pci_addrs = (struct pci_reg_property *) + get_property(np, "assigned-addresses", &l); + i = 0; + if (pci_addrs != 0) { + while ((l -= sizeof(struct pci_reg_property)) >= 0) { + /* XXX assumes PCI addresses mapped 1-1 to physical */ + reg[i].address = pci_addrs[i].addr.a_lo; + reg[i].size = pci_addrs[i].size_lo; + ++i; + } + } else { + rp = (struct reg_property *) get_property(np, "reg", &l); + if (rp != 0) { + while ((l -= sizeof(struct reg_property)) >= 0) { + reg[i].address = rp[i].address + base_address; + reg[i].size = rp[i].size; + ++i; + } + } + } + if (i > 0) { + np->addrs = reg; + np->n_addrs = i; + mem_start += i * sizeof(struct reg_property); + } + + np->intrs = (int *) get_property(np, "AAPL,interrupts", &l); + if (np->intrs != 0) + np->n_intrs = l / sizeof(int); + + /* get the node's full name */ + l = (int) call_prom("package-to-path", 3, 1, node, + (char *) mem_start, mem_end - mem_start); + if (l >= 0) { + np->full_name = (char *) mem_start; + np->full_name[l] = 0; + mem_start = ALIGN(mem_start + l + 1); + } + + if (np->type != 0 && strcmp(np->type, "dbdma") == 0 && np->n_addrs > 0) + base_address = np->addrs[0].address; + + child = call_prom("child", 1, 1, node); + while (child != (void *)0) { + mem_start = inspect_node(child, np, base_address, + mem_start, mem_end); + child = call_prom("peer", 1, 1, child); + } + + return mem_start; +} + +/* + * Construct a return a list of the device_nodes with a given name. + */ +struct device_node * +find_devices(const char *name) +{ + struct device_node *head, **prevp, *np; + + prevp = &head; + for (np = allnodes; np != 0; np = np->allnext) { + if (np->name != 0 && strcasecmp(np->name, name) == 0) { + *prevp = np; + prevp = &np->next; + } + } + *prevp = 0; + return head; +} + +/* + * Construct a return a list of the device_nodes with a given type. + */ +struct device_node * +find_type_devices(const char *type) +{ + struct device_node *head, **prevp, *np; + + prevp = &head; + for (np = allnodes; np != 0; np = np->allnext) { + if (np->type != 0 && strcasecmp(np->type, type) == 0) { + *prevp = np; + prevp = &np->next; + } + } + *prevp = 0; + return head; +} + +/* + * Find the device_node with a given full_name. + */ +struct device_node * +find_path_device(const char *path) +{ + struct device_node *np; + + for (np = allnodes; np != 0; np = np->allnext) + if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) + return np; + return NULL; +} + +/* + * Find a property with a given name for a given node + * and return the value. + */ +unsigned char * +get_property(struct device_node *np, const char *name, int *lenp) +{ + struct property *pp; + + for (pp = np->properties; pp != 0; pp = pp->next) + if (strcmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + return pp->value; + } + return 0; +} + +void +print_properties(struct device_node *np) +{ + struct property *pp; + char *cp; + int i, n; + + for (pp = np->properties; pp != 0; pp = pp->next) { + printk(KERN_INFO "%s", pp->name); + for (i = strlen(pp->name); i < 16; ++i) + printk(" "); + cp = (char *) pp->value; + for (i = pp->length; i > 0; --i, ++cp) + if ((i > 1 && (*cp < 0x20 || *cp > 0x7e)) + || (i == 1 && *cp != 0)) + break; + if (i == 0 && pp->length > 1) { + /* looks like a string */ + printk(" %s\n", (char *) pp->value); + } else { + /* dump it in hex */ + n = pp->length; + if (n > 64) + n = 64; + if (pp->length % 4 == 0) { + unsigned int *p = (unsigned int *) pp->value; + + n /= 4; + for (i = 0; i < n; ++i) { + if (i != 0 && (i % 4) == 0) + printk("\n "); + printk(" %08x", *p++); + } + } else { + unsigned char *bp = pp->value; + + for (i = 0; i < n; ++i) { + if (i != 0 && (i % 16) == 0) + printk("\n "); + printk(" %02x", *bp++); + } + } + printk("\n"); + if (pp->length > 64) + printk(" ... (length = %d)\n", + pp->length); + } + } +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.1.50/linux/arch/ppc/kernel/ptrace.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/ptrace.c Sat Aug 16 09:51:08 1997 @@ -171,8 +171,11 @@ goto repeat; } /* this is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) < max_mapnr) - *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data; + if (MAP_NR(page) < max_mapnr) { + unsigned long phys_addr = page + (addr & ~PAGE_MASK); + *(unsigned long *) phys_addr = data; + flush_icache_range(phys_addr, phys_addr+4); + } /* we're bypassing pagetables, so we have to set the dirty bit ourselves */ /* this should also re-instate whatever read-only mode there was before */ set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); @@ -364,7 +367,7 @@ case PTRACE_PEEKUSR: { unsigned long tmp; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { + if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2)) { ret = -EIO; goto out; } @@ -378,13 +381,11 @@ if (addr < PT_FPR0) { tmp = get_reg(child, addr); } -#if 1 - else if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) { + else if (addr >= PT_FPR0 && addr <= PT_FPSCR) { if (last_task_used_math == child) giveup_fpu(); tmp = ((long *)child->tss.fpr)[addr - PT_FPR0]; } -#endif else ret = -EIO; if (!ret) @@ -400,7 +401,7 @@ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + if ((addr & 3) || addr < 0 || addr >= ((PT_FPR0 + 64) << 2)) goto out; addr = addr >> 2; /* temporary hack. */ @@ -508,7 +509,7 @@ goto out; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.1.50/linux/arch/ppc/kernel/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/setup.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,173 @@ +/* + * $Id: setup.c,v 1.12 1997/08/13 03:06:17 cort Exp $ + * Common prep/pmac boot and setup code. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +char saved_command_line[256]; +unsigned char aux_device_present; + +/* copy of the residual data */ +RESIDUAL res; +int _machine; + +/* + * Find out what kind of machine we're on and save any data we need + * from the early boot process (devtree is copied on pmac by prom_init() ) + */ +unsigned long identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + extern unsigned long initrd_start, initrd_end; + extern char cmd_line[256]; +#ifdef CONFIG_PMAC /* cheat for now - perhaps a check for OF could tell us */ + _machine = _MACH_Pmac; +#endif /* CONFIG_PMAC */ +#ifdef CONFIG_PREP + if (!strncmp(res.VitalProductData.PrintableModel,"IBM",3)) + _machine = _MACH_IBM; + else + _machine = _MACH_Motorola; +#endif /* CONFIG_PREP */ + + if ( _machine == _MACH_Pmac ) + { + io_base = 0; + } + else if ( is_prep ) /* prep */ + { + io_base = 0x80000000; + /* make a copy of residual data */ + if ( r3 ) + memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL) ); + /* take care of initrd if we have one */ + if ( r4 ) + { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } + /* take care of cmd line */ + if ( r6 ) + { + + *(char *)(r7+KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6+KERNELBASE)); + } + } + else + { + printk("Unknown machine type in identify_machine!\n"); + } + return 0; +} + +/* cmd is ignored for now... */ +void machine_restart(char *cmd) +{ + struct cuda_request req; + unsigned long flags; + unsigned long i = 10000; + + if ( _machine == _MACH_Pmac ) + { + cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM); + for (;;) + cuda_poll(); + } + else /* prep */ + { + _disable_interrupts(); + + /* set exception prefix high - to the prom */ + save_flags( flags ); + restore_flags( flags|MSR_IP ); + + /* make sure bit 0 (reset) is a 0 */ + outb( inb(0x92) & ~1L , 0x92 ); + /* signal a reset to system control port A - soft reset */ + outb( inb(0x92) | 1 , 0x92 ); + + while ( i != 0 ) i++; + panic("restart failed\n"); + } + +} + +void machine_power_off(void) +{ + struct cuda_request req; + + if ( _machine == _MACH_Pmac ) + { + cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN); + for (;;) + cuda_poll(); + } + else /* prep */ + { + machine_restart(NULL); + } +} + +void machine_halt(void) +{ + if ( _machine == _MACH_Pmac ) + { +#if 0 + prom_exit(); /* doesn't work because prom is trashed */ +#else + machine_power_off(); /* for now */ +#endif + } + else /* prep */ + machine_restart(NULL); + +} + + +__initfunc(unsigned long +bios32_init(unsigned long memory_start, unsigned long memory_end)) +{ + return memory_start; +} + +/* + * Will merge more into here later -- Cort + */ +int get_cpuinfo(char *buffer) +{ + extern int pmac_get_cpuinfo(char *); + extern int prep_get_cpuinfo(char *); + + if ( _machine == _MACH_Pmac ) + return pmac_get_cpuinfo(buffer); +#ifdef CONFIG_PREP + else /* prep */ + return prep_get_cpuinfo(buffer); +#endif /* CONFIG_PREP */ +} + +__initfunc(void setup_arch(char **cmdline_p, + unsigned long * memory_start_p, unsigned long * memory_end_p)) +{ + extern void pmac_setup_arch(char **, unsigned long *, unsigned long *); + extern void prep_setup_arch(char **, unsigned long *, unsigned long *); + + if ( _machine == _MACH_Pmac ) + pmac_setup_arch(cmdline_p,memory_start_p,memory_end_p); +#ifdef CONFIG_PREP + else /* prep */ + prep_setup_arch(cmdline_p,memory_start_p,memory_end_p); +#endif /* CONFIG_PREP */ +} + + diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c --- v2.1.50/linux/arch/ppc/kernel/signal.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/signal.c Sat Aug 16 09:51:08 1997 @@ -24,6 +24,7 @@ #include #include #include +#include #include #define _S(nr) (1<<((nr)-1)) @@ -36,6 +37,10 @@ #define PAUSE_AFTER_SIGNAL #undef PAUSE_AFTER_SIGNAL +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); /* @@ -71,32 +76,52 @@ } } +/* + * These are the flags in the MSR that the user is allowed to change + * by modifying the saved value of the MSR on the stack. SE and BE + * should not be in this list since gdb may want to change these. I.e, + * you should be able to step out of a signal handler to see what + * instruction executes next after the signal handler completes. + * Alternately, if you stepped into a signal handler, you should be + * able to continue 'til the next breakpoint from within the signal + * handler, even if the handler returns. + */ +#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) + /* * This sets regs->esp even though we don't actually use sigstacks yet.. */ asmlinkage int sys_sigreturn(struct pt_regs *regs) { - struct sigcontext_struct *sc; - struct pt_regs *int_regs; - int signo, ret; + struct sigcontext_struct *sc, sigctx; + int ret; + elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ -#if 1 - if (verify_area(VERIFY_READ, (void *) regs->gpr[1], sizeof(sc)) - || (regs->gpr[1] >= KERNELBASE)) + sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); + if (copy_from_user(&sigctx, sc, sizeof(sigctx))) goto badframe; -#endif - sc = (struct sigcontext_struct *)(regs->gpr[1]+STACK_FRAME_OVERHEAD); - get_user(current->blocked, &sc->oldmask); - current->blocked &= _BLOCKABLE; - get_user(int_regs, &sc->regs); - get_user(signo, &sc->signal); + current->blocked = sigctx.oldmask & _BLOCKABLE; sc++; /* Pop signal 'context' */ #ifdef DEBUG_SIGNALS -printk("Sig return - Regs: %x, sc: %x, sig: %d\n", int_regs, sc, signo); + printk("Sig return - Regs: %p, sc: %p, sig: %d\n", sigctx.regs, sc, + sigctx.signal); #endif - if (sc == (struct sigcontext_struct *)(int_regs)) { - /* Last stacked signal */ - memcpy(regs, int_regs, sizeof(*regs)); + if (sc == (struct sigcontext_struct *)(sigctx.regs)) { + /* Last stacked signal - restore registers */ + if (last_task_used_math == current) + giveup_fpu(); + if (copy_from_user(saved_regs, sigctx.regs, sizeof(saved_regs))) + goto badframe; + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + memcpy(regs, saved_regs, + MIN(sizeof(elf_gregset_t),sizeof(struct pt_regs))); + + if (copy_from_user(current->tss.fpr, + (unsigned long *)sigctx.regs + ELF_NGREG, + ELF_NFPREG * sizeof(double))) + goto badframe; + if (regs->trap == 0x0C00 /* System Call! */ && ((int)regs->result == -ERESTARTNOHAND || (int)regs->result == -ERESTARTSYS || @@ -106,15 +131,17 @@ regs->result = 0; } ret = regs->result; + } else { /* More signals to go */ - regs->gpr[1] = (unsigned long)sc - STACK_FRAME_OVERHEAD; - get_user(regs->gpr[3], &sc->signal); - get_user(int_regs, (struct pt_regs **) &sc->regs); - regs->gpr[4] = (unsigned long) int_regs; - regs->link = (unsigned long) (int_regs+1); - get_user(regs->nip, &sc->handler); - ret = regs->gpr[3]; + regs->gpr[1] = (unsigned long)sc - __SIGNAL_FRAMESIZE; + if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + goto badframe; + regs->gpr[3] = ret = sigctx.signal; + regs->gpr[4] = (unsigned long) sigctx.regs; + regs->link = regs->gpr[4] + ELF_NGREG * sizeof(unsigned long) + + ELF_NFPREG * sizeof(double); + regs->nip = sigctx.handler; } return ret; @@ -142,6 +169,7 @@ unsigned long *frame = NULL; unsigned long *trampoline; unsigned long *regs_ptr; + double *fpregs_ptr; unsigned long nip = 0; unsigned long signr; struct sigcontext_struct *sc; @@ -164,7 +192,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -204,7 +232,7 @@ current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; @@ -257,18 +285,33 @@ nip = regs->nip; frame = (unsigned long *) regs->gpr[1]; - /* Build trampoline code on stack */ - frame -= 2; + /* + * Build trampoline code on stack, and save gp and fp regs. + * The 56 word hole is because programs using the rs6000/xcoff + * style calling sequence can save up to 19 gp regs and 18 fp regs + * on the stack before decrementing sp. + */ + frame -= 2 + 56; trampoline = frame; - /* verify stack is valid for writing regs struct */ - if (verify_area(VERIFY_WRITE,(void *)frame, sizeof(long)*2+sizeof(*regs)) - || ((unsigned long) frame >= KERNELBASE )) - goto badframe; - put_user(0x38007777UL, trampoline); /* li r0,0x7777 */ - put_user(0x44000002UL, trampoline+1); /* sc */ - frame -= sizeof(*regs) / sizeof(long); + frame -= ELF_NFPREG * sizeof(double) / sizeof(unsigned long); + fpregs_ptr = (double *) frame; + frame -= ELF_NGREG; regs_ptr = frame; - copy_to_user(regs_ptr, regs, sizeof(*regs)); + /* verify stack is valid for writing to */ + if (verify_area(VERIFY_WRITE, frame, + (ELF_NGREG + 2) * sizeof(long) + + ELF_NFPREG * sizeof(double))) + goto badframe; + if (last_task_used_math == current) + giveup_fpu(); + if (__copy_to_user(regs_ptr, regs, + MIN(sizeof(elf_gregset_t),sizeof(struct pt_regs))) + || __copy_to_user(fpregs_ptr, current->tss.fpr, + ELF_NFPREG * sizeof(double)) + || __put_user(0x38007777UL, trampoline) /* li r0,0x7777 */ + || __put_user(0x44000002UL, trampoline+1)) /* sc */ + goto badframe; + signr = 1; sa = current->sig->action; @@ -279,24 +322,29 @@ continue; frame -= sizeof(struct sigcontext_struct) / sizeof(long); - if (verify_area(VERIFY_WRITE,(void *)frame, - sizeof(struct sigcontext_struct)/sizeof(long))) + if (verify_area(VERIFY_WRITE, frame, + sizeof(struct sigcontext_struct))) goto badframe; sc = (struct sigcontext_struct *)frame; nip = (unsigned long) sa->sa_handler; if (sa->sa_flags & SA_ONESHOT) sa->sa_handler = NULL; - put_user(nip, &sc->handler); - put_user(oldmask, &sc->oldmask); /* was current->blocked */ - put_user(regs_ptr, &sc->regs); - put_user(signr, &sc->signal); + if (__put_user(nip, &sc->handler) + || __put_user(oldmask, &sc->oldmask) + || __put_user(regs_ptr, &sc->regs) + || __put_user(signr, &sc->signal)) + goto badframe; current->blocked |= sa->sa_mask; regs->gpr[3] = signr; - regs->gpr[4] = (unsigned long)regs_ptr; + regs->gpr[4] = (unsigned long) regs_ptr; } + + frame -= __SIGNAL_FRAMESIZE / sizeof(unsigned long); + if (put_user(regs->gpr[1], frame)) + goto badframe; regs->link = (unsigned long)trampoline; regs->nip = nip; - regs->gpr[1] = (unsigned long)sc - STACK_FRAME_OVERHEAD; + regs->gpr[1] = (unsigned long) frame; /* The DATA cache must be flushed here to insure coherency */ /* between the DATA & INSTRUCTION caches. Since we just */ @@ -305,8 +353,8 @@ /* cache for new data, we have to force the data to go on to */ /* memory and flush the instruction cache to force it to look */ /* there. The following function performs this magic */ - store_cache_range((unsigned long) trampoline, - (unsigned long) (trampoline + 2)); + flush_icache_range((unsigned long) trampoline, + (unsigned long) (trampoline + 2)); return 1; badframe: diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/strcase.c linux/arch/ppc/kernel/strcase.c --- v2.1.50/linux/arch/ppc/kernel/strcase.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/strcase.c Wed Dec 31 16:00:00 1969 @@ -1,12 +0,0 @@ -#include - -int strcasecmp(const char *s1, const char *s2) -{ - int c1, c2; - - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } while (c1 == c2 && c1 != 0); - return c1 - c2; -} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c --- v2.1.50/linux/arch/ppc/kernel/syscalls.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/syscalls.c Sat Aug 16 09:51:08 1997 @@ -1,15 +1,25 @@ /* * linux/arch/ppc/kernel/sys_ppc.c * + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Derived from "arch/i386/kernel/sys_i386.c" * Adapted from the i386 version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au). * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/PPC * platform. + * + * 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 @@ -20,11 +30,11 @@ #include #include #include +#include #include #include #include - void check_bugs(void) { @@ -32,32 +42,32 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) { - printk("sys_ioperm()\n"); + printk(KERN_ERR "sys_ioperm()\n"); return -EIO; } int sys_iopl(int a1, int a2, int a3, int a4) { lock_kernel(); - printk( "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4); + printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4); unlock_kernel(); - return (ENOSYS); + return (-ENOSYS); } int sys_vm86(int a1, int a2, int a3, int a4) { lock_kernel(); - printk( "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4); + printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4); unlock_kernel(); - return (ENOSYS); + return (-ENOSYS); } int sys_modify_ldt(int a1, int a2, int a3, int a4) { lock_kernel(); - printk( "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4); + printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4); unlock_kernel(); - return (ENOSYS); + return (-ENOSYS); } /* @@ -65,7 +75,8 @@ * * This is really horribly ugly. */ -asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) +asmlinkage int +sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) { int version, ret; @@ -73,138 +84,113 @@ version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - if (call <= SEMCTL) - switch (call) { - case SEMOP: - ret = sys_semop (first, (struct sembuf *)ptr, second); - goto out; - case SEMGET: - ret = sys_semget (first, second, third); - goto out; - case SEMCTL: { - union semun fourth; - ret = -EINVAL; - if (!ptr) - goto out; - ret = -EFAULT; - if (get_user(fourth.__pad, (void **) ptr)) - goto out; - ret = sys_semctl (first, second, third, fourth); - goto out; - } - default: - ret = -EINVAL; - goto out; + ret = -EINVAL; + switch (call) { + case SEMOP: + ret = sys_semop (first, (struct sembuf *)ptr, second); + break; + case SEMGET: + ret = sys_semget (first, second, third); + break; + case SEMCTL: { + union semun fourth; + + if (!ptr) + break; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))) + || (ret = get_user(fourth.__pad, (void **)ptr))) + break; + ret = sys_semctl (first, second, third, fourth); + break; } - if (call <= MSGCTL) - switch (call) { - case MSGSND: - ret = sys_msgsnd (first, (struct msgbuf *) ptr, - second, third); - goto out; - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - ret = -EINVAL; - if (!ptr) - goto out; - ret = -EFAULT; - if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, - sizeof (tmp))) - goto out; - ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); - goto out; - } - case 1: default: - ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); - goto out; + case MSGSND: + ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third); + break; + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + + if (!ptr) + break; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))) + || (ret = copy_from_user(&tmp, + (struct ipc_kludge *) ptr, + sizeof (tmp)))) + break; + ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, + third); + break; } - case MSGGET: - ret = sys_msgget ((key_t) first, second); - goto out; - case MSGCTL: - ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); - goto out; default: - ret = -EINVAL; - goto out; + ret = sys_msgrcv (first, (struct msgbuf *) ptr, + second, fifth, third); + break; } - if (call <= SHMCTL) - switch (call) { - case SHMAT: - switch (version) { - case 0: default: { - ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); - if (ret) - goto out; - ret = put_user (raddr, (ulong *) third); - goto out; + break; + case MSGGET: + ret = sys_msgget ((key_t) first, second); + break; + case MSGCTL: + ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); + break; + case SHMAT: + switch (version) { + default: { + ulong raddr; + + if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, + sizeof(ulong)))) + break; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + break; + ret = put_user (raddr, (ulong *) third); + break; } - case 1: /* iBCS2 emulator entry point */ - ret = -EINVAL; - if (get_fs() != get_ds()) - goto out; - ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); - goto out; - } - case SHMDT: - ret = sys_shmdt ((char *)ptr); - goto out; - case SHMGET: - ret = sys_shmget (first, second, third); - goto out; - case SHMCTL: - ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); - goto out; - default: - ret = -EINVAL; - goto out; + case 1: /* iBCS2 emulator entry point */ + if (get_fs() != get_ds()) + break; + ret = sys_shmat (first, (char *) ptr, second, + (ulong *) third); + break; } - else - ret = -EINVAL; -out: - unlock_kernel(); - return ret; -} - + break; + case SHMDT: + ret = sys_shmdt ((char *)ptr); + break; + case SHMGET: + ret = sys_shmget (first, second, third); + break; + case SHMCTL: + ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); + break; + } -#ifndef CONFIG_MODULES -void -scsi_register_module(void) -{ - lock_kernel(); - panic("scsi_register_module"); - unlock_kernel(); -} - -void -scsi_unregister_module(void) -{ - lock_kernel(); - panic("scsi_unregister_module"); unlock_kernel(); + return ret; } -#endif /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -asmlinkage int sys_pipe(unsigned long * fildes) +asmlinkage int sys_pipe(int *fildes) { int fd[2]; int error; - error = verify_area(VERIFY_WRITE,fildes,8); + error = verify_area(VERIFY_WRITE, fildes, 8); if (error) return error; + lock_kernel(); error = do_pipe(fd); + unlock_kernel(); if (error) return error; - put_user(fd[0],0+fildes); - put_user(fd[1],1+fildes); + if (__put_user(fd[0],0+fildes) + || __put_user(fd[1],1+fildes)) + return -EFAULT; /* should we close the fds? */ return 0; } @@ -213,13 +199,18 @@ unsigned long fd, off_t offset) { struct file * file = NULL; + int ret = -EBADF; + + lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - return -EBADF; + goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - return do_mmap(file, addr, len, prot, flags, offset); + ret = do_mmap(file, addr, len, prot, flags, offset); +out: + unlock_kernel(); + return ret; } extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); @@ -233,15 +224,15 @@ asmlinkage int ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { - int err; if ( (unsigned long)n >= 4096 ) { unsigned long *buffer = (unsigned long *)n; - if ( get_user(n, buffer) || - get_user(inp,buffer+1) || - get_user(outp,buffer+2) || - get_user(exp,buffer+3) || - get_user(tvp,buffer+4) ) + if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)) + || __get_user(n, buffer) + || __get_user(inp, ((fd_set **)(buffer+1))) + || __get_user(outp, ((fd_set **)(buffer+2))) + || __get_user(exp, ((fd_set **)(buffer+3))) + || __get_user(tvp, ((struct timeval **)(buffer+4)))) return -EFAULT; } return sys_select(n, inp, outp, exp, tvp); diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.1.50/linux/arch/ppc/kernel/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/time.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,221 @@ +/* + * $Id: time.c,v 1.8 1997/08/11 08:37:51 cort Exp $ + * Common time routines among all ppc machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) to merge + * Paul Mackerras' version and mine for PReP and Pmac. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "time.h" + +/* this is set to the appropriate pmac/prep func in init_IRQ() */ +int (*set_rtc_time)(unsigned long); + +/* keep track of when we need to update the rtc */ +unsigned long last_rtc_update = 0; + +/* The decrementer counts down by 128 every 128ns on a 601. */ +#define DECREMENTER_COUNT_601 (1000000000 / HZ) +#define COUNT_PERIOD_NUM_601 1 +#define COUNT_PERIOD_DEN_601 1000 + +unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ +unsigned count_period_num; /* 1 decrementer count equals */ +unsigned count_period_den; /* count_period_num / count_period_den us */ + +/* Accessor functions for the decrementer register. */ +inline unsigned long +get_dec(void) +{ + int ret; + + asm volatile("mfspr %0,22" : "=r" (ret) :); + return ret; +} + +inline void +set_dec(int val) +{ + asm volatile("mtspr 22,%0" : : "r" (val)); +} + +/* + * timer_interrupt - gets called when the decrementer overflows, + * with interrupts disabled. + * We set it up to overflow again in 1/HZ seconds. + */ +void timer_interrupt(struct pt_regs * regs) +{ + int dval, d; + while ((dval = get_dec()) < 0) { + /* + * Wait for the decrementer to change, then jump + * in and add decrementer_count to its value + * (quickly, before it changes again!) + */ + while ((d = get_dec()) == dval) + ; + set_dec(d + decrementer_count); + do_timer(regs); + /* + * update the rtc when needed + */ + if ( xtime.tv_sec > last_rtc_update + 660 ) + if (set_rtc_time(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +} + +/* + * This version of gettimeofday has microsecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_flags(flags); + cli(); + *tv = xtime; + tv->tv_usec += (decrementer_count - get_dec()) + * count_period_num / count_period_den; + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + restore_flags(flags); +} + +void do_settimeofday(struct timeval *tv) +{ + unsigned long flags; + int frac_tick; + + last_rtc_update = 0; /* so the rtc gets updated soon */ + + frac_tick = tv->tv_usec % (1000000 / HZ); + save_flags(flags); + cli(); + xtime.tv_sec = tv->tv_sec; + xtime.tv_usec = tv->tv_usec - frac_tick; + set_dec(frac_tick * count_period_den / count_period_num); + restore_flags(flags); +} + + +void +time_init(void) +{ +#ifdef CONFIG_PREP + /* pmac hasn't yet called via_cuda_init() */ + if ( _machine != _MACH_Pmac ) /* prep */ + { + xtime.tv_sec = prep_get_rtc_time(); + xtime.tv_usec = 0; + /* + * mark the rtc/on-chip timer as in sync + * so we don't update right away + */ + last_rtc_update = xtime.tv_sec; + } +#endif /* CONFIG_PREP */ + if ((_get_PVR() >> 16) == 1) { + /* 601 processor: dec counts down by 128 every 128ns */ + decrementer_count = DECREMENTER_COUNT_601; + count_period_num = COUNT_PERIOD_NUM_601; + count_period_den = COUNT_PERIOD_DEN_601; + } else { + /* + * These should setup decrementer_count + */ + if ( _machine == _MACH_Pmac ) + pmac_calibrate_decr(); +#ifdef CONFIG_PREP + else /* PReP */ + prep_calibrate_decr(); +#endif /* CONFIG_PREP */ + } + + if ( _machine == _MACH_Pmac ) + set_rtc_time = pmac_set_rtc_time; +#ifdef CONFIG_PREP + else /* prep */ + set_rtc_time = prep_set_rtc_time; +#endif /* CONFIG_PREP */ + + set_dec(decrementer_count); +} + +#ifdef CONFIG_PREP +/* + * Uses the on-board timer to calibrate the on-chip decrementer register + * for prep systems. On the pmac the OF tells us what the frequency is + * but on prep we have to figure it out. + * -- Cort + */ +int calibrate_done = 0; +volatile int *done_ptr = &calibrate_done; +void prep_calibrate_decr(void) +{ + unsigned long flags; + + save_flags(flags); + +#define TIMER0_COUNT 0x40 +#define TIMER_CONTROL 0x43 + /* set timer to periodic mode */ + outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */ + /* set the clock to ~100 Hz */ + outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ + outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ + + if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0) + panic("Could not allocate timer IRQ!"); + __sti(); + while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */ + restore_flags(flags); + free_irq( 0, NULL); +} + +void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs) +{ + int freq, divisor; + static unsigned long t1 = 0, t2 = 0; + + if ( !t1 ) + t1 = get_dec(); + else if (!t2) + { + t2 = get_dec(); + t2 = t1-t2; /* decr's in 1/HZ */ + t2 = t2*HZ; /* # decrs in 1s - thus in Hz */ + freq = t2 * 60; /* try to make freq/1e6 an integer */ + divisor = 60; + printk("time_init: decrementer frequency = %d/%d (%luMHz)\n", + freq, divisor,t2>>20); + decrementer_count = freq / HZ / divisor; + count_period_num = divisor; + count_period_den = freq / 1000000; + *done_ptr = 1; + } +} +#endif /* CONFIG_PREP */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/time.h linux/arch/ppc/kernel/time.h --- v2.1.50/linux/arch/ppc/kernel/time.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/time.h Sat Aug 16 09:51:08 1997 @@ -0,0 +1,25 @@ +/* + * $Id: time.h,v 1.3 1997/08/12 08:22:14 cort Exp $ + * Common time prototypes and such for all ppc machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) to merge + * Paul Mackerras' version and mine for PReP and Pmac. + */ + +/* time.c */ +__inline__ unsigned long get_dec(void); +__inline__ void set_dec(int val); +void prep_calibrate_decr_handler(int, void *,struct pt_regs *); +void prep_calibrate_decr(void); +void pmac_calibrate_decr(void); +extern unsigned decrementer_count; +extern unsigned count_period_num; +extern unsigned count_period_den; + +/* pmac/prep_time.c */ +unsigned long prep_get_rtc_time(void); +unsigned long pmac_get_rtc_time(void); +int prep_set_rtc_time(unsigned long nowtime); +int pmac_set_rtc_time(unsigned long nowtime); +void pmac_read_rtc_time(void); + diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.1.50/linux/arch/ppc/kernel/traps.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/kernel/traps.c Sat Aug 16 09:51:08 1997 @@ -1,9 +1,15 @@ /* * linux/arch/ppc/kernel/traps.c * - * Copyright (C) 1995 Gary Thomas - * Adapted for PowerPC by Gary Thomas + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * 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. + * * Modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au) */ /* @@ -24,9 +30,21 @@ #include #include -#include +#include #include #include +#include + +extern int fix_alignment(struct pt_regs *); +extern void bad_page_fault(struct pt_regs *, unsigned long); + +#ifdef CONFIG_XMON +extern int xmon_bpt(struct pt_regs *regs); +extern int xmon_sstep(struct pt_regs *regs); +extern void xmon(struct pt_regs *regs); +extern int xmon_iabr_match(struct pt_regs *regs); +extern void (*xmon_fault_handler)(struct pt_regs *regs); +#endif /* * Trap & Exception support @@ -43,40 +61,53 @@ if (!user_mode(regs)) { show_regs(regs); - print_backtrace(regs->gpr[1]); - panic("Exception in kernel pc %x signal %d",regs->nip,signr); + print_backtrace((unsigned long *)regs->gpr[1]); +#ifdef CONFIG_XMON + xmon(regs); +#endif + panic("Exception in kernel pc %lx signal %d",regs->nip,signr); } force_sig(signr, current); } +void MachineCheckException(struct pt_regs *regs) { if ( !user_mode(regs) ) { +#ifdef CONFIG_XMON + if (xmon_fault_handler) { + xmon_fault_handler(regs); + return; + } +#endif printk("Machine check in kernel mode.\n"); printk("Caused by (from msr): "); - printk("regs %08x ",regs); + printk("regs %p ",regs); switch( regs->msr & 0x0000F000) { case (1<<12) : printk("Machine check signal - probably due to mm fault\n" "with mmu off\n"); - break; + break; case (1<<13) : printk("Transfer error ack signal\n"); - break; + break; case (1<<14) : printk("Data parity signal\n"); - break; + break; case (1<<15) : printk("Address parity signal\n"); - break; + break; default: printk("Unknown values in msr\n"); } show_regs(regs); - print_backtrace(regs->gpr[1]); - panic(""); + print_backtrace((unsigned long *)regs->gpr[1]); +#ifdef CONFIG_XMON + xmon(regs); +#endif + panic("machine check"); } _exception(SIGSEGV, regs); } @@ -105,33 +136,71 @@ _exception(SIGTRAP, regs); } +void ProgramCheckException(struct pt_regs *regs) { - if (current->flags & PF_PTRACED) + if (regs->msr & 0x100000) { + /* IEEE FP exception */ + _exception(SIGFPE, regs); + } else if (regs->msr & 0x20000) { + /* trap exception */ +#ifdef CONFIG_XMON + if (xmon_bpt(regs)) + return; +#endif _exception(SIGTRAP, regs); - else + } else { _exception(SIGILL, regs); + } } +void SingleStepException(struct pt_regs *regs) { regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ +#ifdef CONFIG_XMON + if (xmon_sstep(regs)) + return; +#endif _exception(SIGTRAP, regs); } +void AlignmentException(struct pt_regs *regs) { + int fixed; + + if (last_task_used_math == current) + giveup_fpu(); + fixed = fix_alignment(regs); + if (fixed == 1) { + regs->nip += 4; /* skip over emulated instruction */ + return; + } + if (fixed == -EFAULT) { + /* fixed == -EFAULT means the operand address was bad */ + bad_page_fault(regs, regs->dar); + return; + } _exception(SIGBUS, regs); } +void +PromException(struct pt_regs *regs, int trap) +{ + regs->trap = trap; +#ifdef CONFIG_XMON + xmon(regs); +#endif + printk("Exception %lx in prom at PC: %lx, SR: %lx\n", + regs->trap, regs->nip, regs->msr); + /* probably should turn up the toes here */ +} + +void trace_syscall(struct pt_regs *regs) { - static int count; - printk("Task: %08X(%d), PC: %08X/%08X, Syscall: %3d, Result: %s%d\n", + printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n", current, current->pid, regs->nip, regs->link, regs->gpr[0], regs->ccr&0x10000000?"Error=":"", regs->gpr[3]); - if (++count == 20) - { - count = 0; - } } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/ld.script linux/arch/ppc/ld.script --- v2.1.50/linux/arch/ppc/ld.script Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/ld.script Wed Dec 31 16:00:00 1969 @@ -1,81 +0,0 @@ -OUTPUT_ARCH(powerpc) -SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); -/* Do we need any of these for elf? - __DYNAMIC = 0; */ -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .rel.text : { *(.rel.text) } - .rela.text : { *(.rela.text) } - .rel.data : { *(.rel.data) } - .rela.data : { *(.rela.data) } - .rel.rodata : { *(.rel.rodata) } - .rela.rodata : { *(.rela.rodata) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.bss : { *(.rel.bss) } - .rela.bss : { *(.rela.bss) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : { *(.init) } =0 - .plt : { *(.plt) } - .text : - { - *(.text) - *(.fixup) - *(.got1) - } - _etext = .; - PROVIDE (etext = .); - .rodata : - { - *(.rodata) - *(.rodata1) - } - .fini : { *(.fini) } =0 - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - /* Read-write section, merged into data segment: */ - . = (. + 0x0FFF) & 0xFFFFF000; - .data : - { - *(.data) - *(.data1) - *(.sdata) - *(.sdata2) - *(.got.plt) *(.got) - *(.dynamic) - CONSTRUCTORS - } - _edata = .; -/* - . = ALIGN(4096); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(4096); - __init_end = .; -*/ - __bss_start = .; /* BSS */ - PROVIDE (edata = .); - __bss_start = .; - .bss : - { - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); -} - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile --- v2.1.50/linux/arch/ppc/lib/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/lib/Makefile Sat Aug 16 09:51:08 1997 @@ -1,38 +1,11 @@ -.c.s: - $(CC) $(CFLAGS) -S $< -.s.o: - $(AS) $(ASFLAGS) -o $*.o $< -.c.o: - $(CC) $(CFLAGS) -c $< -.S.s: - $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s -.S.o: - $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s - $(AS) $(ASFLAGS) -o $*.o $*.s - rm $*.s - -HOST_CC = gcc - -L_TARGET = lib.o -L_OBJS = checksum.o cksum_support.o string.o - -${L_TARGET}: $(L_OBJS) - $(LD) -r -o ${L_TARGET} $(L_OBJS) - - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend - -dep: - $(CPP) -M *.S *.c > .depend +# +# Makefile for ppc-specific library files.. +# -modules: +.S.o: + $(CC) -D__ASSEMBLY__ -c $< -o $*.o -dummy: +O_TARGET = lib.o +O_OBJS = checksum.o string.o strcase.o -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/checksum.S linux/arch/ppc/lib/checksum.S --- v2.1.50/linux/arch/ppc/lib/checksum.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/lib/checksum.S Sat Aug 16 09:51:08 1997 @@ -0,0 +1,192 @@ +/* + * This file contains assembly-language implementations + * of IP-style 1's complement checksum routines. + * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * 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. + * + * Severely hacked about by Paul Mackerras (paulus@cs.anu.edu.au). + */ + +#include +#include +#include "../kernel/ppc_asm.tmpl" + +_TEXT() + +/* + * ip_fast_csum(buf, len) -- Optimized for IP header + * len is in words and is always >= 5. + */ +_GLOBAL(ip_fast_csum) + lwz r0,0(r3) + lwzu r5,4(r3) + addi r4,r4,-2 + addc r0,r0,r5 + mtctr r4 +1: lwzu r4,4(r3) + adde r0,r0,r4 + bdnz 1b + addze r0,r0 /* add in final carry */ + rlwinm r3,r0,16,0,31 /* fold two halves together */ + add r3,r0,r3 + not r3,r3 + srwi r3,r3,16 + blr + +/* + * Compute checksum of TCP or UDP pseudo-header: + * csum_tcpudp_magic(saddr, daddr, len, proto, sum) + */ +_GLOBAL(csum_tcpudp_magic) + rlwimi r5,r6,16,0,15 /* put proto in upper half of len */ + addc r0,r3,r4 /* add 4 32-bit words together */ + adde r0,r0,r5 + adde r0,r0,r7 + addze r0,r0 /* add in final carry */ + rlwinm r3,r0,16,0,31 /* fold two halves together */ + add r3,r0,r3 + not r3,r3 + srwi r3,r3,16 + blr + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * csum_partial(buff, len, sum) + */ +_GLOBAL(csum_partial) + addic r0,r5,0 + subi r3,r3,4 + srwi. r6,r4,2 + beq 3f /* if we're doing < 4 bytes */ + andi. r5,r3,2 /* Align buffer to longword boundary */ + beq+ 1f + lhz r5,4(r3) /* do 2 bytes to get aligned */ + addi r3,r3,2 + subi r4,r4,2 + addc r0,r0,r5 + srwi. r6,r4,2 /* # words to do */ + beq 3f +1: mtctr r6 +2: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */ + adde r0,r0,r5 /* be unnecessary to unroll this loop */ + bdnz 2b + andi. r4,r4,3 +3: cmpi 0,r4,2 + blt+ 4f + lhz r5,4(r3) + addi r3,r3,2 + subi r4,r4,2 + adde r0,r0,r5 +4: cmpi 0,r4,1 + bne+ 5f + lbz r5,4(r3) + slwi r5,r5,8 /* Upper byte of word */ + adde r0,r0,r5 +5: addze r3,r0 /* add in final carry */ + blr + +/* + * Computes the checksum of a memory block at src, length len, + * and adds in "sum" (32-bit), while copying the block to dst. + * If an access exception occurs on src or dst, it stores -EFAULT + * to *src_err or *dst_err respectively, and (for an error on + * src) zeroes the rest of dst. + * + * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err) + */ +_GLOBAL(csum_partial_copy_generic) + addic r0,r6,0 + subi r3,r3,4 + subi r4,r4,4 + srwi. r6,r5,2 + beq 3f /* if we're doing < 4 bytes */ + andi. r9,r4,2 /* Align dst to longword boundary */ + beq+ 1f +81: lhz r6,4(r3) /* do 2 bytes to get aligned */ + addi r3,r3,2 + subi r5,r5,2 +91: sth r6,4(r4) + addi r4,r4,2 + addc r0,r0,r6 + srwi. r6,r5,2 /* # words to do */ + beq 3f +1: mtctr r6 +82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */ +92: stwu r6,4(r4) /* be unnecessary to unroll this loop */ + adde r0,r0,r6 + bdnz 82b + andi. r5,r5,3 +3: cmpi 0,r5,2 + blt+ 4f +83: lhz r6,4(r3) + addi r3,r3,2 + subi r5,r5,2 +93: sth r6,4(r4) + addi r4,r4,2 + adde r0,r0,r6 +4: cmpi 0,r5,1 + bne+ 5f +84: lbz r6,4(r3) +94: stb r6,4(r4) + slwi r6,r6,8 /* Upper byte of word */ + adde r0,r0,r6 +5: addze r3,r0 /* add in final carry */ + blr + +.section .fixup,"ax" + +src_error_1: + li r6,0 + subi r5,r5,2 +95: sth r6,4(r4) + addi r4,r4,2 + srwi. r6,r5,2 + beq 3f + mtctr r6 +src_error_2: + li r6,0 +96: stwu r6,4(r4) + bdnz 96b +3: andi. r5,r5,3 + beq src_error +src_error_3: + li r6,0 + mtctr r5 + addi r4,r4,3 +97: stbu r6,1(r4) + bdnz 97b +src_error: + cmpi 0,r7,0 + beq 1f + li r6,-EFAULT + stw r6,0(r7) +1: addze r3,r0 + blr + +dst_error: + cmpi 0,r8,0 + beq 1f + li r6,-EFAULT + stw r6,0(r8) +1: addze r3,r0 + blr + +.section __ex_table,"a" + .long 81b,src_error_1 + .long 91b,dst_error + .long 82b,src_error_2 + .long 92b,dst_error + .long 83b,src_error_3 + .long 93b,dst_error + .long 84b,src_error_3 + .long 94b,dst_error + .long 95b,dst_error + .long 96b,dst_error + .long 97b,dst_error diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/checksum.c linux/arch/ppc/lib/checksum.c --- v2.1.50/linux/arch/ppc/lib/checksum.c Wed Dec 18 00:49:52 1996 +++ linux/arch/ppc/lib/checksum.c Wed Dec 31 16:00:00 1969 @@ -1,136 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, - * Arnt Gulbrandsen, - * Tom May, - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * Adapted for PowerPC by Gary Thomas - * - * 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 - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) -{ - unsigned long result = ~_csum_partial(buff, len, sum); -#if 0 -printk("Csum partial(%x, %d, %x) = %x\n", buff, len, sum, result); -dump_buf(buff, len); -#endif - return result; -} - -/* - * the same as csum_partial, but copies from src while it - * checksums - * - * here even more important to align src and dst on a 32-bit boundary - */ - -unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum) -{ - /* - * The whole idea is to do the copy and the checksum at - * the same time, but we do it the easy way now. - * - * At least csum on the source, not destination, for cache - * reasons.. - */ - sum = csum_partial(src, len, sum); - memcpy(dst, src, len); - return sum; -} - -extern unsigned short _ip_fast_csum(unsigned char *buf); - -unsigned short -ip_fast_csum(unsigned char *buf, unsigned int len) -{ - unsigned short _val; - _val = _ip_fast_csum(buf); -#if 0 - printk("IP CKSUM(%x, %d) = %x\n", buf, len, _val); - dump_buf(buf, len*4); -#endif - return (_val); -} - -extern unsigned short _ip_compute_csum(unsigned char *buf, int len); - -unsigned short -ip_compute_csum(unsigned char *buf, int len) -{ - unsigned short _val; - _val = _ip_compute_csum(buf, len); -#if 0 - printk("Compute IP CKSUM(%x, %d) = %x\n", buf, len, _val); - dump_buf(buf, len); -#endif - return (_val); -} - -unsigned short -_udp_check(unsigned char *buf, int len, int saddr, int daddr, int hdr); - -unsigned short -udp_check(unsigned char *buf, int len, int saddr, int daddr) -{ - unsigned short _val; - int hdr; - hdr = (len << 16) + IPPROTO_UDP; - _val = _udp_check(buf, len, saddr, daddr, hdr); -#if 0 - printk("UDP CSUM(%x,%d,%x,%x) = %x\n", buf, len, saddr, daddr, _val); - dump_buf(buf, len); -#endif - return (_val); -} - -unsigned short -_tcp_check(unsigned char *buf, int len, int saddr, int daddr, int hdr); - -unsigned short -csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) -{ - unsigned short _val; - _val = _csum_tcpudp_magic(saddr, daddr, sum, (len<<16)+proto); -#if 0 - printk("TCP Magic(%x, %x, %x, %x) = %x\n", saddr, daddr, (len<<16)+proto, sum, _val); -#endif - return (_val); -} - -/* - * Fold a partial checksum without adding pseudo headers - */ - -unsigned int csum_fold(unsigned int sum) -{ - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return ~sum; -} - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/cksum_support.S linux/arch/ppc/lib/cksum_support.S --- v2.1.50/linux/arch/ppc/lib/cksum_support.S Mon May 27 02:00:58 1996 +++ linux/arch/ppc/lib/cksum_support.S Wed Dec 31 16:00:00 1969 @@ -1,125 +0,0 @@ -/* - * This module contains the PowerPC interrupt fielders - * set of code at specific locations, based on function - */ - -#include -#include "../kernel/ppc_asm.tmpl" - -_TEXT() - -/* - * Compute IP checksums - * _ip_fast_csum(buf, len) -- Optimized for IP header - * _ip_compute_csum(buf, len) - */ - -_GLOBAL(_ip_fast_csum) - li r0,0 - addic r0,r0,0 /* Clear initial carry */ - lwz r4,0(r3) - lwz r5,4(r3) - adde r0,r0,r4 - lwz r4,8(r3) - adde r0,r0,r5 - lwz r5,12(r3) - adde r0,r0,r4 - lwz r4,16(r3) - adde r0,r0,r5 - adde r0,r0,r4 - mr r3,r0 - andi. r3,r3,0xFFFF - srwi r0,r0,16 - adde r3,r3,r0 - andis. r0,r3,1 - beq 10f - addi r3,r3,1 -10: not r3,r3 - andi. r3,r3,0xFFFF - blr - -_GLOBAL(_ip_compute_csum) - li r0,0 - addic r0,r0,0 -finish_ip_csum: - subi r3,r3,4 - andi. r5,r3,2 /* Align buffer to longword boundary */ - beq 10f - lhz r5,4(r3) - adde r0,r0,r5 - addi r3,r3,2 - subi r4,r4,2 -10: cmpi 0,r4,16 /* unrolled loop - 16 bytes at a time */ - blt 20f - lwz r5,4(r3) - lwz r6,8(r3) - adde r0,r0,r5 - lwz r5,12(r3) - adde r0,r0,r6 - lwzu r6,16(r3) - adde r0,r0,r5 - adde r0,r0,r6 - subi r4,r4,16 - b 10b -20: cmpi 0,r4,4 - blt 30f - lwzu r5,4(r3) - adde r0,r0,r5 - subi r4,r4,4 - b 20b -30: cmpi 0,r4,2 - blt 40f - lhz r5,4(r3) - addi r3,r3,2 - adde r0,r0,r5 - subi r4,r4,2 -40: cmpi 0,r4,1 - bne 50f - lbz r5,4(r3) - slwi r5,r5,8 /* Upper byte of word */ - adde r0,r0,r5 -50: mr r3,r0 - andi. r3,r3,0xFFFF - srwi r0,r0,16 - adde r3,r3,r0 - andis. r0,r3,1 - beq 60f - addi r3,r3,1 -60: not r3,r3 - andi. r3,r3,0xFFFF - blr - -_GLOBAL(_udp_check) - addc r0,r5,r6 /* Add in header fields */ - adde r0,r0,r7 - b finish_ip_csum - -_GLOBAL(_tcp_check) - addc r0,r5,r6 /* Add in header fields */ - adde r0,r0,r7 - b finish_ip_csum - -_GLOBAL(_csum_partial) - li r0,0 - addc r0,r5,r0 - b finish_ip_csum - -/* - * Compute 16 bit sum: - * _csum_tcpudp_magic(int saddr, int daddr, int sum, int proto) - */ -_GLOBAL(_csum_tcpudp_magic) - addc r0,r3,r4 - adde r0,r0,r5 - adde r0,r0,r6 - mr r3,r0 - andi. r3,r3,0xFFFF - srwi r0,r0,16 - adde r3,r3,r0 - andis. r0,r3,1 /* Carry out of 16 bits? */ - beq 10f - addi r3,r3,1 -10: not r3,r3 - andi. r3,r3,0xFFFF - blr - diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/strcase.c linux/arch/ppc/lib/strcase.c --- v2.1.50/linux/arch/ppc/lib/strcase.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/lib/strcase.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,12 @@ +#include + +int strcasecmp(const char *s1, const char *s2) +{ + int c1, c2; + + do { + c1 = tolower(*s1++); + c2 = tolower(*s2++); + } while (c1 == c2 && c1 != 0); + return c1 - c2; +} diff -u --recursive --new-file v2.1.50/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S --- v2.1.50/linux/arch/ppc/lib/string.S Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/lib/string.S Sat Aug 16 09:51:08 1997 @@ -94,6 +94,7 @@ 8: stbu r4,1(r6) bdnz 8b blr + .globl bcopy bcopy: mr r6,r3 @@ -189,7 +190,7 @@ .globl memcmp memcmp: cmpwi 0,r5,0 - blelr + ble- 2f mtctr r5 addi r6,r3,-1 addi r4,r4,-1 @@ -198,6 +199,22 @@ subf. r3,r0,r3 bdnzt 2,1b blr +2: li r3,0 + blr + + .global memchr +memchr: + cmpwi 0,r5,0 + ble- 2f + mtctr r5 + addi r3,r3,-1 +1: lbzu r0,1(r3) + cmpw 0,r0,r4 + bdnzf 2,1b + beqlr +2: li r3,0 + blr + .globl __copy_tofrom_user __copy_tofrom_user: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mkdist linux/arch/ppc/mkdist --- v2.1.50/linux/arch/ppc/mkdist Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mkdist Sat Aug 16 09:51:08 1997 @@ -1,9 +1,13 @@ #!/bin/bash -N=`basename $PWD` -V=`echo $N | sed 's/linux-//'` +V=`egrep ^VERSION Makefile | awk '{print $3}'` +P=`egrep ^PATCHLEVEL Makefile | awk '{print $3}'` +S=`egrep ^SUBLEVEL Makefile | awk '{print $3}'` date=`date +'%y%m%d'` -mkdir -p ../dist -mv zImage ../dist/zImage-$V-$date -mv System.map ../dist/System.map-$V-$date + +echo zImage-$V.$P.$S-$date +echo System.map-$V.$P.$S-$date + +rcp zImage charon:ppc/dist/kernel-images/zImage-$V.$P.$S-$date +rcp System.map charon:ppc/dist/kernel-images/System.map-$V.$P.$S-$date diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mktar linux/arch/ppc/mktar --- v2.1.50/linux/arch/ppc/mktar Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mktar Sat Aug 16 09:51:08 1997 @@ -1,7 +1,9 @@ #!/bin/bash -N=`basename $PWD` +V=`egrep ^VERSION Makefile | awk '{print $3}'` +P=`egrep ^PATCHLEVEL Makefile | awk '{print $3}'` +S=`egrep ^SUBLEVEL Makefile | awk '{print $3}'` date=`date +'%y%m%d'` cd ../ mkdir -p dist -tar -zcf dist/ppc$N-$date.tar.gz -X $N/arch/ppc/ignore $N +tar -vzcf ppclinux-$V.$P.$S-$date.tar.gz -X linux/arch/ppc/ignore linux diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile --- v2.1.50/linux/arch/ppc/mm/Makefile Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mm/Makefile Sat Aug 16 09:51:08 1997 @@ -7,28 +7,7 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -.c.o: - $(CC) $(CFLAGS) -c $< -.s.o: - $(AS) -o $*.o $< -.c.s: - $(CC) $(CFLAGS) -S $< +O_TARGET := mm.o +O_OBJS = fault.o init.o extable.o -OBJS = fault.o init.o extable.o - -mm.o: $(OBJS) - $(LD) -r -o mm.o $(OBJS) - -modules: - -dep: - -fastdep: - $(TOPDIR)/scripts/mkdep *.[Sch] > .depend - -# -# include a dependency file if one exists -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v2.1.50/linux/arch/ppc/mm/fault.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mm/fault.c Sat Aug 16 09:51:08 1997 @@ -1,8 +1,12 @@ /* * arch/ppc/mm/fault.c * - * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds - * Ported to PPC by Gary Thomas + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Derived from "arch/i386/mm/fault.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * * Modified by Cort Dougan and Paul Mackerras. * * This program is free software; you can redistribute it and/or @@ -26,40 +30,42 @@ #include #include +#include #include +#include +#include -#ifdef CONFIG_PMAC +#ifdef CONFIG_XMON +extern void xmon(struct pt_regs *); extern void (*xmon_fault_handler)(void); -#endif - -/* the linux norm for the function name is show_regs() so - make it call dump_regs() on the mac -- Cort */ -#ifdef CONFIG_PMAC -#define show_regs dump_regs +extern int xmon_dabr_match(struct pt_regs *); +int xmon_kernel_faults; #endif extern void die_if_kernel(char *, struct pt_regs *, long); void bad_page_fault(struct pt_regs *, unsigned long); void do_page_fault(struct pt_regs *, unsigned long, unsigned long); -void print_pte(struct _PTE); -void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) +/* + * The error_code parameter is DSISR for a data fault, SRR1 for + * an instruction fault. + */ +void do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code) { - struct task_struct *tsk = current; - extern unsigned _end[]; struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - pgd_t *dir; - pmd_t *pmd; - pte_t *pte; - - /*printk("do_page_fault() %s/%d addr %x nip %x regs %x error %x\n", - current->comm,current->pid,address,regs->nip,regs,error_code);*/ -#ifdef CONFIG_PMAC + +#ifdef CONFIG_XMON if (xmon_fault_handler && regs->trap == 0x300) { xmon_fault_handler(); return; } + if (error_code & 0x00400000) { + /* DABR match */ + if (xmon_dabr_match(regs)) + return; + } #endif if (in_interrupt()) { static int complained; @@ -68,14 +74,18 @@ printk("page fault in interrupt handler, addr=%lx\n", address); show_regs(regs); +#ifdef CONFIG_XMON + if (xmon_kernel_faults) + xmon(regs); +#endif } } - if (current == NULL) - goto bad_area; - -do_page: + if (current == NULL) { + bad_page_fault(regs, address); + return; + } down(&mm->mmap_sem); - vma = find_vma(tsk->mm, address); + vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma->vm_start <= address) @@ -84,7 +94,7 @@ goto bad_area; if (expand_stack(vma, address)) goto bad_area; - + good_area: if (error_code & 0xb5700000) /* an error such as lwarx to I/O controller space, @@ -98,67 +108,45 @@ /* a read */ } else { /* protection fault */ - if ( error_code & 0x08000000 ) + if (error_code & 0x08000000) goto bad_area; if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } handle_mm_fault(current, vma, address, error_code & 0x02000000); - up(&mm->mmap_sem); - /*printk("do_page_fault() return %s/%d addr %x msr %x\n", - current->comm,current->pid,address,regs->msr);*/ - /* not needed since flush_page_to_ram() works */ -#if 0 - flush_page(address); -#endif + up(&mm->mmap_sem); return; - + bad_area: - up(¤t->mm->mmap_sem); + up(&mm->mmap_sem); bad_page_fault(regs, address); } - void bad_page_fault(struct pt_regs *regs, unsigned long address) { - extern unsigned int probingmem; - struct task_struct *tsk = current; unsigned long fixup; - + + if (user_mode(regs)) { + force_sig(SIGSEGV, current); + return; + } /* Are we prepared to handle this fault? */ if ((fixup = search_exception_table(regs->nip)) != 0) { - if ( user_mode(regs) ) - printk("Exception from user mode\n"); -#if 0 - printk(KERN_DEBUG "Exception at %lx (%lx)\n", regs->nip, fixup); -#endif regs->nip = fixup; return; } - if ( user_mode(regs) ) - { - force_sig(SIGSEGV, tsk); - return; - } - -bad_kernel_access: - /* make sure it's not a bootup probe test */ - if ( probingmem ) - { - probingmem = 0; - return; - } /* kernel has accessed a bad area */ show_regs(regs); - print_backtrace( regs->gpr[1] ); -#ifdef CONFIG_PMAC - xmon(regs); + print_backtrace( (unsigned long *)regs->gpr[1] ); +#ifdef CONFIG_XMON + if (xmon_kernel_faults) + xmon(regs); #endif - panic("kernel access of bad area\n pc %x address %X tsk %s/%d", - regs->nip,address,tsk->comm,tsk->pid); + panic("kernel access of bad area\n pc %lx address %lX tsk %s/%d", + regs->nip,address,current->comm,current->pid); } unsigned long va_to_phys(unsigned long address) @@ -189,6 +177,10 @@ return (0); } +#if 0 +/* + * Misc debugging functions. Please leave them here. -- Cort + */ void print_pte(struct _PTE p) { printk( @@ -210,7 +202,8 @@ for ( ptr = Hash ; ptr < Hash_end ; ptr++ ) { if ( ptr->rpn == (address>>12) ) - printk("phys %08X -> va ???\n", + printk("phys %08lX -> va ???\n", address); } } +#endif diff -u --recursive --new-file v2.1.50/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.1.50/linux/arch/ppc/mm/init.c Mon Aug 4 16:25:36 1997 +++ linux/arch/ppc/mm/init.c Sat Aug 16 09:51:08 1997 @@ -31,54 +31,48 @@ #include #include #include -#ifdef CONFIG_PMAC #include -#endif #include #include #include #include -#ifdef CONFIG_PREP #include +#ifdef CONFIG_BLK_DEV_INITRD +#include /* for initrd_* */ #endif +int prom_trashed; int next_mmu_context; +unsigned long _SDR1; +PTE *Hash, *Hash_end; +unsigned long Hash_size, Hash_mask; +unsigned long *end_of_DRAM; +int mem_init_done; extern pgd_t swapper_pg_dir[]; extern char _start[], _end[]; extern char etext[], _stext[]; -/* References to section boundaries */ extern char __init_begin, __init_end; +extern RESIDUAL res; -extern void die_if_kernel(char *,struct pt_regs *,long); -extern void show_net_buffers(void); -extern unsigned long *find_end_of_memory(void); -#undef MAP_RAM_WITH_SEGREGS 1 - -#ifdef CONFIG_PMAC void *find_mem_piece(unsigned, unsigned); static void mapin_ram(void); static void inherit_prom_translations(void); -#endif -#ifdef CONFIG_PREP -inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va); -int inline MMU_hash_page(struct task_struct *,unsigned long,pte *); -#endif - static void hash_init(void); static void *MMU_get_page(void); -void map_page(struct thread_struct *, unsigned long va, +void map_page(struct task_struct *, unsigned long va, unsigned long pa, int flags); +extern void die_if_kernel(char *,struct pt_regs *,long); +extern void show_net_buffers(void); +extern unsigned long *find_end_of_memory(void); -PTE *Hash, *Hash_end; -unsigned long Hash_size, Hash_mask; -unsigned long *end_of_DRAM; -int mem_init_done; +/* + * this tells the prep system to map all of ram with the segregs + * instead of the bats. I'd like to get this to apply to the + * pmac as well then have everything use the bats -- Cort + */ +#undef MAP_RAM_WITH_SEGREGS 1 -#ifdef CONFIG_PREP -#ifdef HASHSTATS -extern unsigned long evicts; -#endif /* HASHSTATS */ /* * these are used to setup the initial page tables * They can waste up to an entire page since the @@ -88,8 +82,6 @@ unsigned int probingmem = 0; unsigned int mmu_pages_count = 0; char mmu_pages[(MAX_MMU_PAGES+1)*PAGE_SIZE]; -unsigned long _TotalMemory; -#endif /* CONFIG_PREP */ /* * BAD_PAGE is the page that is used for page faults when linux @@ -120,7 +112,6 @@ return pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED)); } -#ifdef CONFIG_PMAC #define MAX_MEM_REGIONS 32 phandle memory_pkg; @@ -128,7 +119,6 @@ int n_regions; struct reg_property regions[MAX_MEM_REGIONS]; }; - struct mem_pieces phys_mem; struct mem_pieces phys_avail; struct mem_pieces prom_mem; @@ -138,7 +128,6 @@ static void print_mem_pieces(struct mem_pieces *); unsigned long avail_start; -int prom_trashed; /* * Read in a property describing some pieces of memory. @@ -272,7 +261,7 @@ * Our text, data, bss use something over 1MB, starting at 0. * Open Firmware may be using 1MB at the 4MB point. */ -unsigned long *find_end_of_memory(void) +unsigned long *pmac_find_end_of_memory(void) { unsigned long a, total; unsigned long h, kstart, ksize; @@ -353,6 +342,9 @@ int i; unsigned long a, free; unsigned long start, end; + + if ( _machine != _MACH_Pmac ) + return 0; free = 0; for (i = 0; i < phys_avail.n_regions - 1; ++i) { @@ -366,7 +358,6 @@ avail_start = (unsigned long) __va(a); return avail_start; } -#endif /* CONFIG_PMAC */ void show_mem(void) { @@ -399,14 +390,21 @@ "Ctx", "Ctx<<4", "Last Sys", "pc", "task"); for_each_task(p) { - printk("%-8.8s %3d %3d %8d %8d %8d %c%08x %08x", + printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ", p->comm,p->pid, 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, - p); + (ulong)p); if ( p == current ) - printk(" current"); + printk("current"); + if ( p == last_task_used_math ) + { + if ( p == current ) + printk(","); + printk("last math"); + } + printk("\n"); } } @@ -434,76 +432,68 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) { unsigned long addr; -#ifdef CONFIG_PMAC int i; - unsigned long lim; -#endif + unsigned long a, lim; int codepages = 0; int datapages = 0; int initpages = 0; end_mem &= PAGE_MASK; high_memory = (void *) end_mem; - num_physpages = max_mapnr = MAP_NR(high_memory); - - /* clear the zero-page */ - memset(empty_zero_page, 0, PAGE_SIZE); - + max_mapnr = MAP_NR(high_memory); + num_physpages = max_mapnr; /* RAM is assumed contiguous */ + /* mark usable pages in the mem_map[] */ start_mem = PAGE_ALIGN(start_mem); - -#ifdef CONFIG_PMAC - remove_mem_piece(&phys_avail, __pa(avail_start), - start_mem - avail_start, 1); - - for (a = KERNELBASE ; a < end_mem; a += PAGE_SIZE) - set_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - - for (i = 0; i < phys_avail.n_regions; ++i) { - a = (unsigned long) __va(phys_avail.regions[i].address); - lim = a + phys_avail.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - mem_map[MAP_NR(a)].count = 1; - free_page(a); - } - } - phys_avail.n_regions = 0; - /* free the prom's memory */ - for (i = 0; i < prom_mem.n_regions; ++i) { - a = (unsigned long) __va(prom_mem.regions[i].address); - lim = a + prom_mem.regions[i].size; - a = PAGE_ALIGN(a); - for (; a < lim; a += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); - mem_map[MAP_NR(a)].count = 1; - free_page(a); + if ( _machine == _MACH_Pmac ) + { + remove_mem_piece(&phys_avail, __pa(avail_start), + start_mem - avail_start, 1); + + for (addr = KERNELBASE ; addr < end_mem; addr += PAGE_SIZE) + set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + + for (i = 0; i < phys_avail.n_regions; ++i) { + a = (unsigned long) __va(phys_avail.regions[i].address); + lim = a + phys_avail.regions[i].size; + a = PAGE_ALIGN(a); + for (; a < lim; a += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); + } + phys_avail.n_regions = 0; + + /* free the prom's memory */ + for (i = 0; i < prom_mem.n_regions; ++i) { + a = (unsigned long) __va(prom_mem.regions[i].address); + lim = a + prom_mem.regions[i].size; + a = PAGE_ALIGN(a); + for (; a < lim; a += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); } + prom_trashed = 1; } - prom_trashed = 1; -#endif /* CONFIG_PMAC */ - -#ifdef CONFIG_PREP - /* mark mem used by kernel as reserved, mark other unreserved */ - for (addr = PAGE_OFFSET ; addr < end_mem; addr += PAGE_SIZE) + else /* prep */ { - /* skip hash table gap */ - if ( (addr > (ulong)_end) && (addr < (ulong)Hash)) - continue; - if ( addr < (ulong) /*Hash_end*/ start_mem ) - set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); - else - clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + /* mark mem used by kernel as reserved, mark other unreserved */ + for (addr = PAGE_OFFSET ; addr < end_mem; addr += PAGE_SIZE) + { + /* skip hash table gap */ + if ( (addr > (ulong)_end) && (addr < (ulong)Hash)) + continue; + if ( addr < (ulong) /*Hash_end*/ start_mem ) + set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + else + clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + } } for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) { - if(PageReserved(mem_map + MAP_NR(addr))) { + if (PageReserved(mem_map + MAP_NR(addr))) { if (addr < (ulong) etext) codepages++; - /*else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end)) - initpages++;*/ + else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end)) + initpages++; else if (addr < (ulong) start_mem) datapages++; continue; @@ -515,9 +505,8 @@ #endif /* CONFIG_BLK_DEV_INITRD */ free_page(addr); } - -#endif /* CONFIG_PREP */ - printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", + + printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), @@ -534,7 +523,6 @@ */ void free_initmem(void) { - unsigned long addr; unsigned long a; unsigned long num_freed_pages = 0; @@ -548,16 +536,14 @@ num_freed_pages++; } -#if 0 - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - num_freed_pages++; - mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - mem_map[MAP_NR(addr)].count = 1; - free_page(addr); + a = (unsigned long)(&__init_begin); + for (; a < (unsigned long)(&__init_end); a += PAGE_SIZE) { + mem_map[MAP_NR(a)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(a)].count, 1); + free_page(a); } -#endif - printk ("Freeing unused kernel memory: %dk freed\n", + + printk ("Freeing unused kernel memory: %ldk freed\n", (num_freed_pages * PAGE_SIZE) >> 10); } @@ -576,19 +562,13 @@ val->totalram++; if (!atomic_read(&mem_map[i].count)) continue; - val->sharedram += atomic_read(&mem_map[i].count)-1; + val->sharedram += atomic_read(&mem_map[i].count) - 1; } val->totalram <<= PAGE_SHIFT; val->sharedram <<= PAGE_SHIFT; return; } -/* Kernel MMU setup & lowest level hardware support */ - -unsigned long _SDR1; /* Hardware SDR1 image */ - -#ifdef CONFIG_PREP - BAT BAT0 = { { @@ -635,7 +615,11 @@ 0x00000000>>17, /* brpn */ 0, /* w */ 0, /* i */ +#ifdef __SMP__ 1, /* m */ +#else + 0, /* m */ +#endif 0, /* g */ BPP_RW /* pp */ } @@ -724,61 +708,41 @@ * this will likely stay seperate from the pmac. * -- Cort */ -unsigned long *find_end_of_memory(void) +unsigned long *prep_find_end_of_memory(void) { - extern RESIDUAL res; - extern unsigned long resptr; - int i, p; + int i; unsigned long h; - - /* copy residual data */ - if ( resptr ) - memcpy( &res, (void *)(resptr+KERNELBASE), sizeof(RESIDUAL) ); - else - /* clearing bss probably clears this but... */ - memset( &res, sizeof(RESIDUAL), 0 ); - _TotalMemory = res.TotalMemory; - - /* this really has nothing to do with the mmu_init() but is - necessary for early setup -- Cort */ - if (!strncmp(res.VitalProductData.PrintableModel,"IBM",3)) - { - _machine = _MACH_IBM; - } - else - _machine = _MACH_Motorola; - /* setup the hash table */ - if (_TotalMemory == 0 ) + if (res.TotalMemory == 0 ) { /* * I need a way to probe the amount of memory if the residual * data doesn't contain it. -- Cort */ printk("Ramsize from residual data was 0 -- Probing for value\n"); - _TotalMemory = 0x03000000; - printk("Ramsize default to be %dM\n", _TotalMemory>>20); + res.TotalMemory = 0x03000000; + printk("Ramsize default to be %ldM\n", res.TotalMemory>>20); } #if 0 /* linux has trouble with > 64M ram -- Cort */ - if ( _TotalMemory > 0x04000000 /* 64M */ ) + if ( res.TotalMemory > 0x04000000 /* 64M */ ) { printk("Only using first 64M of ram.\n"); - _TotalMemory = 0x04000000; + res.TotalMemory = 0x04000000; } #endif /* setup the bat2 mapping to cover physical ram */ BAT2.batu.bl = 0x1; /* 256k mapping */ - for ( h = 256*1024 /* 256k */ ; (h <= _TotalMemory) && (h <= 256*1024*1024); + for ( h = 256*1024 /* 256k */ ; (h <= res.TotalMemory) && (h <= 256*1024*1024); h *= 2 ) BAT2.batu.bl = (BAT2.batu.bl << 1) | BAT2.batu.bl; /* * Allow 64k of hash table for every 16MB of memory, * up to a maximum of 2MB. */ - for (h = 64<<10; h < _TotalMemory / 256 && h < 2<<20; h *= 2) + for (h = 64<<10; h < res.TotalMemory / 256 && h < 2<<20; h *= 2) ; Hash_size = h; Hash_mask = (h >> 6) - 1; @@ -799,11 +763,11 @@ if ( _get_PVR() == 1 ) { /* map in rest of ram with seg regs */ - if ( _TotalMemory > 0x01000000 /* 16M */) + if ( res.TotalMemory > 0x01000000 /* 16M */) { for (i = KERNELBASE+0x01000000; - i < KERNELBASE+_TotalMemory; i += PAGE_SIZE) - map_page(&init_task.tss, i, __pa(i), + i < KERNELBASE+res.TotalMemory; i += PAGE_SIZE) + map_page(&init_task, i, __pa(i), _PAGE_PRESENT| _PAGE_RW|_PAGE_DIRTY|_PAGE_ACCESSED); } } @@ -815,25 +779,23 @@ memset(&BAT2_601, sizeof(BAT2), 0); /* in case we're on a 601 */ memset(&BAT3_601, sizeof(BAT2), 0); /* map all of ram for kernel with segregs */ - for (i = KERNELBASE; i < KERNELBASE+_TotalMemory; i += PAGE_SIZE) + for (i = KERNELBASE; i < KERNELBASE+res.TotalMemory; i += PAGE_SIZE) { if ( i < (unsigned long)etext ) - map_page(&init_task.tss, i, __pa(i), + map_page(&init_task, i, __pa(i), _PAGE_PRESENT/*| _PAGE_RW*/|_PAGE_DIRTY|_PAGE_ACCESSED); else - map_page(&init_task.tss, i, __pa(i), + map_page(&init_task, i, __pa(i), _PAGE_PRESENT| _PAGE_RW|_PAGE_DIRTY|_PAGE_ACCESSED); } #endif /* MAP_RAM_WITH_SEGREGS */ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", - _TotalMemory >> 20, Hash_size >> 10, Hash); - return ((unsigned long *)_TotalMemory); + res.TotalMemory >> 20, Hash_size >> 10, Hash); + return ((unsigned long *)res.TotalMemory); } -#endif /* CONFIG_PREP */ -#ifdef CONFIG_PMAC /* * Map in all of physical memory starting at KERNELBASE. */ @@ -854,7 +816,10 @@ f = _PAGE_PRESENT | _PAGE_ACCESSED; if ((char *) v < _stext || (char *) v >= etext) f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE; - map_page(&init_task.tss, v, p, f); + else + /* On the powerpc, no user access forces R/W kernel access */ + f |= _PAGE_USER; + map_page(&init_task, v, p, f); v += PAGE_SIZE; p += PAGE_SIZE; } @@ -889,7 +854,7 @@ for (tp = prom_translations, i = 0; i < n_translations; ++i, ++tp) { /* ignore stuff mapped down low */ - if (tp->virt < 0x10000000) + if (tp->virt < 0x10000000 && tp->phys < 0x10000000) continue; /* map PPC mmu flags to linux mm flags */ f = (tp->flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU @@ -900,13 +865,12 @@ p = tp->phys; n = tp->size; for (; n != 0; n -= PAGE_SIZE) { - map_page(&init_task.tss, v, p, f); + map_page(&init_task, v, p, f); v += PAGE_SIZE; p += PAGE_SIZE; } } } -#endif /* * Initialize the hash table and patch the instructions in head.S. @@ -943,8 +907,8 @@ * out from the data cache and invalidated in the instruction * cache, on those machines with split caches. */ - store_cache_range((unsigned long) hash_page_patch_A, - (unsigned long) (hash_page_patch_C + 1)); + flush_icache_range((unsigned long) hash_page_patch_A, + (unsigned long) (hash_page_patch_C + 1)); } @@ -958,71 +922,74 @@ void MMU_init(void) { - end_of_DRAM = find_end_of_memory(); + if ( _machine == _MACH_Pmac ) + end_of_DRAM = pmac_find_end_of_memory(); + else /* prep */ + end_of_DRAM = prep_find_end_of_memory(); + hash_init(); _SDR1 = __pa(Hash) | (Hash_mask >> 10); -#ifdef CONFIG_PMAC - /* Force initial page tables */ - /* this done by INIT_TSS in processor.h on prep -- Cort */ - init_task.tss.pg_tables = (unsigned long *)swapper_pg_dir; - - /* Map in all of RAM starting at KERNELBASE */ - mapin_ram(); - /* Copy mappings from the prom */ - inherit_prom_translations(); -#endif /* CONFIG_PMAC */ + + if ( _machine == _MACH_Pmac ) + { + /* Map in all of RAM starting at KERNELBASE */ + mapin_ram(); + /* Copy mappings from the prom */ + inherit_prom_translations(); + } } static void * MMU_get_page() { - void *p; - - if (mem_init_done) { - p = (void *) __get_free_page(GFP_KERNEL); - if (p == 0) - panic("couldn't get a page in MMU_get_page"); - } else { -#ifdef CONFIG_PREP - mmu_pages_count++; - if ( mmu_pages_count > MAX_MMU_PAGES ) - printk("out of mmu pages!\n"); - p = (pte *)(PAGE_ALIGN((unsigned long)mmu_pages)+ - (mmu_pages_count+PAGE_SIZE)); -#endif -#ifdef CONFIG_PMAC - p = find_mem_piece(PAGE_SIZE, PAGE_SIZE); -#endif - } - memset(p, 0, PAGE_SIZE); - return p; + void *p; + + if (mem_init_done) { + p = (void *) __get_free_page(GFP_KERNEL); + if (p == 0) + panic("couldn't get a page in MMU_get_page"); + } else { + if ( is_prep ) + { + mmu_pages_count++; + if ( mmu_pages_count > MAX_MMU_PAGES ) + printk("out of mmu pages!\n"); + p = (pte *)(PAGE_ALIGN((unsigned long)mmu_pages)+ + (mmu_pages_count+PAGE_SIZE)); + } + else /* pmac */ + { + p = find_mem_piece(PAGE_SIZE, PAGE_SIZE); + } + } + memset(p, 0, PAGE_SIZE); + return p; } -#ifdef CONFIG_PMAC void * ioremap(unsigned long addr, unsigned long size) { unsigned long p, end = addr + size; for (p = addr & PAGE_MASK; p < end; p += PAGE_SIZE) - map_page(&init_task.tss, p, p, pgprot_val(PAGE_KERNEL_CI) | _PAGE_GUARDED); + map_page(&init_task, p, p, pgprot_val(PAGE_KERNEL_CI) | _PAGE_GUARDED); return (void *) addr; } -#endif void -map_page(struct thread_struct *tss, unsigned long va, +map_page(struct task_struct *tsk, unsigned long va, unsigned long pa, int flags) { pmd_t *pd; pte_t *pg; + - if (tss->pg_tables == NULL) { + if (tsk->mm->pgd == NULL) { /* Allocate upper level page map */ - tss->pg_tables = (unsigned long *) MMU_get_page(); + tsk->mm->pgd = (pgd_t *) MMU_get_page(); } /* Use upper 10 bits of VA to index the first level map */ - pd = (pmd_t *) (tss->pg_tables + (va >> PGDIR_SHIFT)); + pd = (pmd_t *) (tsk->mm->pgd + (va >> PGDIR_SHIFT)); if (pmd_none(*pd)) { /* Need to allocate second-level table */ pg = (pte_t *) MMU_get_page(); @@ -1084,26 +1051,6 @@ } } - -void -flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - unsigned vsid; - - if ( vmaddr < TASK_SIZE) { - /*vsid = (vma->vm_mm->context << 4) | (vmaddr >> 28);*/ - flush_hash_page(vma->vm_mm->context/*vsid*/, vmaddr); - /* this is needed on prep at the moment -- don't know why - -- Cort*/ - MMU_invalidate_page(vma->vm_mm,vmaddr); - } - else - { - /*printk("flush_tlb_page() vmaddr > TASK_SIZE %08x\n", vmaddr);*/ - } -} - - /* for each page addr in the range, call MMU_invalidate_page() if the range is very large and the hash table is small it might be faster to do a search of the hash table and just invalidate pages that are in the range @@ -1113,15 +1060,10 @@ void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - start &= PAGE_MASK; + start &= PAGE_MASK; for (; start < end && start < TASK_SIZE; start += PAGE_SIZE) { - /*flush_hash_page(VSID_FROM_CONTEXT( start>>28, mm->context), - start );*/ flush_hash_page(mm->context, start); - /* this is needed on prep at the moment -- don't know why - -- Cort*/ - MMU_invalidate_page(mm,start); } } @@ -1135,78 +1077,17 @@ mmu_context_overflow(void) { struct task_struct *tsk; - int nr; - printk(KERN_INFO "mmu_context_overflow\n"); - for (nr = 0; nr < NR_TASKS; ++nr) { - tsk = task[nr]; - if (tsk && tsk->mm) + printk(KERN_DEBUG "mmu_context_overflow\n"); + read_lock(&tasklist_lock); + for_each_task(tsk) { + if (tsk->mm) tsk->mm->context = NO_CONTEXT; } + read_unlock(&tasklist_lock); flush_hash_segments(0x10, 0xffffff); - _tlbia(); next_mmu_context = 0; -} - -#ifdef CONFIG_PREP -/* - * it's not a simple matter to get rid of these and switch to the - * ones paul is using. it will take some time and thought -- Cort - */ -inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va) -{ - int hash, page_index, segment, i, h, _h, api, vsid, perms; - PTE *_pte, *slot; - int flags = 0; - page_index = ((int)va & 0x0FFFF000) >> 12; - segment = (unsigned int)va >> 28; - api = page_index >> 10; - vsid = VSID_FROM_CONTEXT(segment,mm->context); - for (_h = 0; _h < 2; _h++) - { - hash = page_index ^ vsid; - if (_h) - { - hash = ~hash; /* Secondary hash uses ones-complement */ - } - hash &= 0x3FF | (Hash_mask /*<< 10*/); - hash *= 8; /* Eight entries / hash bucket */ - _pte = &Hash[hash]; - for (i = 0; i < 8; i++, _pte++) - { - if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api) - { /* Found it! */ - _tlbie(va); /* Clear TLB */ - if (_pte->r) flags |= _PAGE_ACCESSED; - if (_pte->c) flags |= _PAGE_DIRTY; - _pte->v = 0; - return /*(flags)*/; - } - } - } - _tlbie(va); - return /*(flags)*/; -} -#endif - -#include -void print_mm_info(void) -{ - struct _SEGREG s; - long a; - struct _BATU bu; - struct _BATL bl; - unsigned long i; - - for ( i = 0x70000000 ; i <= 0x90000000 ; i+= 0x10000000 ) - { - a = get_SR(i); - memcpy(&s,&a,4); - printk("sr %2d t:%1d ks:%d kp:%d n:%d vsid:%x %x\n", - i>>28, s.t, s.ks, s.kp, s.n, s.vsid, a); - } - - asm("mfspr %0,532; mfspr %1, 533\n" : "=r" (bu), "=r" (bl)); - printk("bat2 bepi: %0x vs: %1x vp: %1x wimg: %x%x%x%x pp: %1x\n", - bu.bepi<<17, bu.vs, bu.vp, bl.w, bl.i, bl.m, bl.g, bl.pp); + /* make sure current always has a context */ + current->mm->context = MUNGE_CONTEXT(++next_mmu_context); + set_context(current->mm->context); } diff -u --recursive --new-file v2.1.50/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig --- v2.1.50/linux/arch/ppc/pmac_defconfig Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/pmac_defconfig Sat Aug 16 09:51:08 1997 @@ -0,0 +1,274 @@ +# +# Automatically generated make config: don't edit +# + +# +# Platform support +# +CONFIG_NATIVE=y +CONFIG_PMAC=y +# CONFIG_PREP is not set +CONFIG_MCOMMON=y +# CONFIG_M601 is not set +# CONFIG_M603 is not set +# CONFIG_M604 is not set + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KERNELD=y +CONFIG_PCI=y +CONFIG_NET=y +CONFIG_SYSCTL=y +CONFIG_SYSVIPC=y +CONFIG_BINFMT_ELF=y +CONFIG_KERNEL_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_BINFMT_JAVA=m +CONFIG_PMAC_CONSOLE=y +CONFIG_MAC_KEYBOARD=y +CONFIG_MAC_FLOPPY=y +CONFIG_PROC_DEVICETREE=y +CONFIG_XMON=y +CONFIG_ATY_VIDEO=y +CONFIG_IMSTT_VIDEO=y + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Floppy, IDE, and other block devices +# +# 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_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +# CONFIG_BLK_DEV_TRITON is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_EZ is not set +# CONFIG_BLK_DEV_HD is not set + +# +# 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=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_PPA is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +CONFIG_SCSI_MESH=y +CONFIG_SCSI_MESH_SYNC_RATE=10 +CONFIG_SCSI_MAC53C94=y +CONFIG_SCSI_QLOGIC_PMAC=m + +# +# Network device support +# + +# +# Networking options +# +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +CONFIG_NET_ALIAS=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ACCT is not set +# CONFIG_IP_ROUTER is not set +CONFIG_NET_IPIP=m +# 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_PCTCP is not set +CONFIG_INET_RARP=y +CONFIG_PATH_MTU_DISCOVERY=y +CONFIG_IP_NOSR=y +CONFIG_SKB_LARGE=y +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_AX25 is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_WAN_ROUTER is not set +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +CONFIG_MACE=y +CONFIG_DEC_ELCP=m +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_EISA is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# +# CONFIG_NET_RADIO is not set +# CONFIG_SLIP is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +CONFIG_MINIX_FS=m +CONFIG_EXT2_FS=y +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_UMSDOS_FS is not set +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 +# CONFIG_SMB_FS is not set +CONFIG_ISO9660_FS=y +# CONFIG_HPFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_AUTOFS_FS=y +# CONFIG_UFS_FS is not set +CONFIG_MAC_PARTITION=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_PRINTER is not set +# CONFIG_MOUSE is not set +# CONFIG_UMISC is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_FTAPE is not set +# CONFIG_APM is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +CONFIG_NVRAM=y +# CONFIG_JOYSTICK is not set + +# +# Sound +# +CONFIG_SOUND=m +# CONFIG_PAS is not set +# CONFIG_SB is not set +# CONFIG_ADLIB is not set +# CONFIG_GUS is not set +# CONFIG_MPU401 is not set +# CONFIG_PSS is not set +# CONFIG_GUS16 is not set +# CONFIG_GUSMAX is not set +# CONFIG_MSS is not set +# CONFIG_SSCAPE is not set +# CONFIG_TRIX is not set +# CONFIG_MAD16 is not set +# CONFIG_CS4232 is not set +# CONFIG_MAUI is not set +# CONFIG_YM3812 is not set +CONFIG_LOWLEVEL_SOUND=y +# CONFIG_ACI_MIXER is not set +# CONFIG_AWE32_SYNTH is not set +# CONFIG_AEDSP16 is not set +CONFIG_AWACS=y diff -u --recursive --new-file v2.1.50/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig --- v2.1.50/linux/arch/ppc/prep_defconfig Mon Aug 4 16:25:37 1997 +++ linux/arch/ppc/prep_defconfig Sat Aug 16 09:51:08 1997 @@ -1,30 +1,31 @@ # # Automatically generated by make menuconfig: don't edit # + +# +# Platform support +# CONFIG_NATIVE=y # CONFIG_PMAC is not set CONFIG_PREP=y -# CONFIG_HEARTBEAT is not set -# CONFIG_POWERSAVING is not set CONFIG_MCOMMON=y # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KERNELD=y CONFIG_PCI=y CONFIG_PCI_OPTIMIZE=y CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y -# CONFIG_BINFMT_JAVA is not set CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_JAVA is not set # # Plug and Play support @@ -46,10 +47,10 @@ # CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_TRITON is not set # CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y -# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_EZ is not set # CONFIG_BLK_DEV_HD is not set @@ -100,7 +101,6 @@ # CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_MESH is not set # CONFIG_SCSI_MAC53C94 is not set -# CONFIG_SCSI_QLOGIC_PMAC is not set # # Network device support @@ -117,6 +117,7 @@ # CONFIG_IP_ACCT is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_SYN_COOKIES is not set # CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set CONFIG_PATH_MTU_DISCOVERY=y @@ -155,6 +156,7 @@ # CONFIG_DEC_ELCP is not set # CONFIG_DGRS is not set # CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_TLAN is not set # CONFIG_ES3210 is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set @@ -183,16 +185,13 @@ # CONFIG_QUOTA is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y -CONFIG_BEXT2_FS=y -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -# CONFIG_RNFS_BOOTP is not set -# CONFIG_RNFS_RARP is not set +# CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y @@ -205,7 +204,6 @@ # CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set CONFIG_MAC_PARTITION=y -CONFIG_HFS_FS=y # # Character devices @@ -213,12 +211,7 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -# CONFIG_SERIAL_SHARE_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_PRINTER is not set CONFIG_MOUSE=y @@ -227,13 +220,39 @@ # 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_FTAPE is not set # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_NVRAM is not set +# CONFIG_JOYSTICK is not set # # Sound # -# CONFIG_SOUND is not set +#CONFIG_SOUND=y +# CONFIG_PAS is not set +# CONFIG_SB is not set +# CONFIG_ADLIB is not set +# CONFIG_GUS is not set +# CONFIG_MPU401 is not set +# CONFIG_PSS is not set +# CONFIG_GUS16 is not set +# CONFIG_GUSMAX is not set +# CONFIG_MSS is not set +# CONFIG_SSCAPE is not set +# CONFIG_TRIX is not set +# CONFIG_MAD16 is not set +CONFIG_CS4232=y +# CONFIG_MAUI is not set +# CONFIG_YM3812 is not set +CS4232_BASE=830 +CS4232_IRQ=10 +CS4232_DMA=6 +CS4232_DMA2=7 +CS4232_MPU_BASE=330 +CS4232_MPU_IRQ=9 +# CONFIG_LOWLEVEL_SOUND is not set diff -u --recursive --new-file v2.1.50/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.1.50/linux/arch/ppc/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/vmlinux.lds Sat Aug 16 09:51:08 1997 @@ -0,0 +1,80 @@ +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } +/* .init : { *(.init) } =0*/ + .plt : { *(.plt) } + .text : + { + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.got.plt) *(.got) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/aplib.c linux/arch/sparc/ap1000/aplib.c --- v2.1.50/linux/arch/sparc/ap1000/aplib.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/aplib.c Sat Aug 16 09:51:08 1997 @@ -455,7 +455,8 @@ while (counter == aplib->rbuf_flag1 + aplib->rbuf_flag2) { tnet_check_completion(); - if (need_resched) break; + if (resched_needed()) + break; if (current->signal & ~current->blocked) break; } return 0; diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/mpp.c linux/arch/sparc/ap1000/mpp.c --- v2.1.50/linux/arch/sparc/ap1000/mpp.c Tue May 13 22:41:03 1997 +++ linux/arch/sparc/ap1000/mpp.c Sat Aug 16 09:51:08 1997 @@ -28,7 +28,7 @@ void mpp_schedule(struct cap_request *req) { mpp_current_task = req->data[0]; - need_resched = 1; + resched_force(); mark_bh(TQUEUE_BH); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/msc.c linux/arch/sparc/ap1000/msc.c --- v2.1.50/linux/arch/sparc/ap1000/msc.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/msc.c Sat Aug 16 09:51:08 1997 @@ -338,7 +338,7 @@ #endif MSC_OUT(MSC_INTR, AP_SET_INTR_MASK << MSC_INTR_QBMFUL_SH); intr_mask |= (AP_INTR_REQ << MSC_INTR_QBMFUL_SH); - need_resched = 1; + resched_force(); block_parallel_tasks = 1; mark_bh(TQUEUE_BH); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/ap1000/tnet.c linux/arch/sparc/ap1000/tnet.c --- v2.1.50/linux/arch/sparc/ap1000/tnet.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/tnet.c Sat Aug 16 09:51:08 1997 @@ -613,7 +613,7 @@ static void reschedule(void) { - need_resched = 1; + resched_force(); mark_bh(TQUEUE_BH); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.1.50/linux/arch/sparc/defconfig Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/defconfig Sat Aug 16 09:51:08 1997 @@ -49,6 +49,7 @@ # CONFIG_SUN_OPENPROMIO=m CONFIG_SUN_MOSTEK_RTC=y +# CONFIG_SAB82532 is not set # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set @@ -105,6 +106,7 @@ CONFIG_IP_ALIAS=m # CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_XTP is not set # # (it is safe to leave these untouched) @@ -184,7 +186,7 @@ CONFIG_EXT2_FS=y CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m +# CONFIG_VFAT_FS is not set # CONFIG_UMSDOS_FS is not set CONFIG_PROC_FS=y CONFIG_NFS_FS=y @@ -207,6 +209,7 @@ CONFIG_UFS_FS=y CONFIG_BSD_DISKLABEL=y CONFIG_SMD_DISKLABEL=y +# CONFIG_MAC_PARTITION is not set # # Kernel hacking diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.1.50/linux/arch/sparc/kernel/process.c Thu Jul 17 10:06:03 1997 +++ linux/arch/sparc/kernel/process.c Sat Aug 16 10:00:14 1997 @@ -105,6 +105,8 @@ /* This is being executed in task 0 'user space'. */ int cpu_idle(void *unused) { + extern volatile int smp_commenced; + current->priority = -100; while(1) { /* @@ -118,7 +120,8 @@ } /* endless idle loop with no priority at all */ current->counter = -100; - schedule(); + if(!smp_commenced || resched_needed()) + schedule(); } } diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c --- v2.1.50/linux/arch/sparc/kernel/ptrace.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/kernel/ptrace.c Sat Aug 16 09:51:08 1997 @@ -886,7 +886,7 @@ current->exit_code = SIGTRAP; current->state = TASK_STOPPED; current->tss.flags ^= MAGIC_CONSTANT; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S --- v2.1.50/linux/arch/sparc/kernel/rtrap.S Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/rtrap.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.46 1997/04/01 02:21:48 davem Exp $ +/* $Id: rtrap.S,v 1.47 1997/08/10 04:49:24 davem Exp $ * rtrap.S: Return from Sparc trap low-level code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -65,12 +65,14 @@ wr %t_psr, 0x0, %psr b ret_trap_kernel - nop + mov 1, %o0 1: + ld [%curptr + AOFF_task_processor], %o1 ld [%twin_tmp1 + %lo(C_LABEL(need_resched))], %g2 + sll %o0, %o1, %o0 - cmp %g2, 0 + andcc %g2, %o0, %g0 be signal_p nop diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.1.50/linux/arch/sparc/kernel/signal.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/kernel/signal.c Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.74 1997/05/15 19:57:09 davem Exp $ +/* $Id: signal.c,v 1.75 1997/08/05 19:19:26 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -722,7 +722,7 @@ /* This happens to be SMP safe so no need to * grab master kernel lock even in this case. */ - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -773,7 +773,7 @@ /* notify_parent() is SMP safe */ if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c --- v2.1.50/linux/arch/sparc/kernel/smp.c Thu May 15 16:48:01 1997 +++ linux/arch/sparc/kernel/smp.c Sat Aug 16 09:51:08 1997 @@ -87,7 +87,7 @@ #define SMP_PRINTK(x) #endif -static volatile int smp_commenced = 0; +volatile int smp_commenced = 0; static char smp_buf[512]; @@ -558,7 +558,7 @@ /* Reschedule call back. */ void smp_reschedule_irq(void) { - need_resched=1; + resched_force(); } /* Running cross calls. */ @@ -623,7 +623,7 @@ if(--current->counter < 0) { current->counter = 0; - need_resched = 1; + resched_force(); } spin_lock(&ticker_lock); diff -u --recursive --new-file v2.1.50/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.1.50/linux/arch/sparc/kernel/sys_sunos.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/kernel/sys_sunos.c Sat Aug 16 10:00:14 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.81 1997/07/20 05:59:31 davem Exp $ +/* $Id: sys_sunos.c,v 1.80 1997/07/17 02:20:22 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.1.50/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.1.50/linux/arch/sparc/mm/srmmu.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/mm/srmmu.c Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.149 1997/07/20 05:59:34 davem Exp $ +/* $Id: srmmu.c,v 1.150 1997/07/25 23:06:17 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -2601,7 +2601,7 @@ } /* turbosparc.S */ -extern void turbosparc_flush_cache_all(); +extern void turbosparc_flush_cache_all(void); extern void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); static void poke_turbosparc(void) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.1.50/linux/arch/sparc64/config.in Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/config.in Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.9 1997/07/04 11:33:05 davem Exp $ +# $Id: config.in,v 1.10 1997/08/11 14:35:45 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -43,6 +43,7 @@ define_bool CONFIG_SUN_CONSOLE y define_bool CONFIG_SUN_AUXIO y define_bool CONFIG_SUN_IO y + define_bool CONFIG_PCI y source drivers/sbus/char/Config.in fi diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.1.50/linux/arch/sparc64/defconfig Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/defconfig Sat Aug 16 09:51:08 1997 @@ -29,6 +29,7 @@ CONFIG_SUN_CONSOLE=y CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y +CONFIG_PCI=y # # SBUS Frame Buffer support @@ -49,6 +50,7 @@ # CONFIG_SUN_OPENPROMIO=m CONFIG_SUN_MOSTEK_RTC=y +# CONFIG_SAB82532 is not set # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set CONFIG_SUN_OPENPROMFS=m @@ -85,6 +87,7 @@ # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_XTP is not set # # (it is safe to leave these untouched) @@ -187,6 +190,7 @@ CONFIG_UFS_FS=m CONFIG_BSD_DISKLABEL=y CONFIG_SMD_DISKLABEL=y +# CONFIG_MAC_PARTITION is not set # # Kernel hacking diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.1.50/linux/arch/sparc64/kernel/Makefile Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/Makefile Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.30 1997/07/24 14:48:04 davem Exp $ +# $Id: Makefile,v 1.34 1997/08/12 04:12:36 ecd Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -29,9 +29,10 @@ O_TARGET := kernel.o O_OBJS := process.o setup.o cpu.o idprom.o \ - systbls.o traps.o devices.o auxio.o ioport.o \ + 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 + unaligned.o sys_sunos32.o sunos_ioctl32.o \ + central.o psycho.o ebus.o OX_OBJS := sparc64_ksyms.o ifdef SMP diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/auxio.c linux/arch/sparc64/kernel/auxio.c --- v2.1.50/linux/arch/sparc64/kernel/auxio.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/auxio.c Sat Aug 16 09:51:08 1997 @@ -3,15 +3,20 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include #include #include #include +#include + #include #include #include #include +#include +#include /* Probe and map in the Auxiliary I/O register */ unsigned char *auxio_register; @@ -31,9 +36,32 @@ } if (!sdev) { +#ifdef CONFIG_PCI + struct linux_ebus *ebus; + struct linux_ebus_device *edev = 0; + + for_all_ebusdev(edev, ebus) + if (!strcmp(edev->prom_name, "auxio")) + break; + + if (edev) { + auxio_register = (unsigned char *) + sparc_alloc_io(edev->regs[0].phys_addr, 0, + edev->regs[0].reg_size, + "auxiliaryIO", + edev->regs[0].which_io, 0x0); + *(auxio_register) = 0x01; + return; + } +#endif + if(central_bus) { + auxio_register = NULL; + return; + } prom_printf("Cannot find auxio node, cannot continue...\n"); prom_halt(); } + prom_getproperty(sdev->prom_node, "reg", (char *) auxregs, sizeof(auxregs)); prom_apply_sbus_ranges(sdev->my_bus, auxregs, 0x1, sdev); /* Map the register both read and write */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c --- v2.1.50/linux/arch/sparc64/kernel/central.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/central.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,131 @@ +/* $Id: central.c,v 1.3 1997/08/12 14:51:55 davem Exp $ + * central.c: Central FHC driver for Sunfire/Starfire/Wildfire. + * + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + */ + +#include +#include +#include + +#include +#include + +struct linux_central *central_bus = NULL; + +static inline unsigned long long_align(unsigned long addr) +{ + return ((addr + (sizeof(unsigned long) - 1)) & + ~(sizeof(unsigned long) - 1)); +} + +extern void prom_central_ranges_init(int cnode, struct linux_central *central); +extern void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc); + +unsigned long central_probe(unsigned long memory_start) +{ + struct linux_prom_registers fpregs[6]; + struct linux_fhc *fhc; + char namebuf[128]; + int cnode, fnode, err; + + prom_printf("CENTRAL: "); + printk("CENTRAL: "); + cnode = prom_finddevice("/central"); + if(cnode == 0 || cnode == -1) { + prom_printf("no central found.\n"); + printk("no central found.\n"); + return memory_start; + } + prom_printf("found central PROM node.\n"); + printk("found central PROM node.\n"); + + /* Ok we got one, grab some memory for software state. */ + memory_start = long_align(memory_start); + central_bus = (struct linux_central *) (memory_start); + + prom_printf("CENTRAL: central_bus[%p] ", central_bus); + memory_start += sizeof(struct linux_central); + memory_start = long_align(memory_start); + fhc = (struct linux_fhc *)(memory_start); + memory_start += sizeof(struct linux_fhc); + memory_start = long_align(memory_start); + + prom_printf("fhc[%p] ", fhc); + + /* First init central. */ + central_bus->child = fhc; + central_bus->prom_node = cnode; + + prom_getstring(cnode, "name", namebuf, sizeof(namebuf)); + strcpy(central_bus->prom_name, namebuf); + + prom_printf("init_central_ranges "); + prom_central_ranges_init(cnode, central_bus); + + /* And then central's FHC. */ + fhc->next = NULL; + fhc->parent = central_bus; + fnode = prom_searchsiblings(prom_getchild(cnode), "fhc"); + if(fnode == 0 || fnode == -1) { + prom_printf("Critical error, central board lacks fhc.\n"); + prom_halt(); + } + fhc->prom_node = fnode; + prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); + strcpy(fhc->prom_name, namebuf); + + prom_printf("cnode[%x] fnode[%x] init_fhc_ranges\n", cnode, fnode); + prom_fhc_ranges_init(fnode, fhc); + + /* Finally, map in FHC register set. (From the prtconf dumps + * I have seen on Ex000 boxes only the central ranges need to + * be applied to the fhc internal register set) -DaveM + */ + err = prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)); + if(err == -1) { + prom_printf("CENTRAL: fatal error, cannot get fhc regs.\n"); + prom_halt(); + } + prom_apply_central_ranges(central_bus, &fpregs[0], 6); + prom_printf("CENTRAL: FHC_REGS[(%08x,%08x) (%08x,%08x) " + "(%08x,%08x) (%08x,%08x) (%08x,%08x) (%08x,%08x)]\n", + fpregs[0].which_io, fpregs[0].phys_addr, + fpregs[1].which_io, fpregs[1].phys_addr, + fpregs[2].which_io, fpregs[2].phys_addr, + fpregs[3].which_io, fpregs[3].phys_addr, + fpregs[4].which_io, fpregs[4].phys_addr, + fpregs[5].which_io, fpregs[5].phys_addr); + fhc->fhc_regs.pregs = (struct fhc_internal_regs *) + __va((((unsigned long)fpregs[0].which_io)<<32) | + (((unsigned long)fpregs[0].phys_addr))); + fhc->fhc_regs.ireg = (struct fhc_ign_reg *) + __va((((unsigned long)fpregs[1].which_io)<<32) | + (((unsigned long)fpregs[1].phys_addr))); + fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *) + __va((((unsigned long)fpregs[2].which_io)<<32) | + (((unsigned long)fpregs[2].phys_addr))); + fhc->fhc_regs.sregs = (struct fhc_system_regs *) + __va((((unsigned long)fpregs[3].which_io)<<32) | + (((unsigned long)fpregs[3].phys_addr))); + fhc->fhc_regs.uregs = (struct fhc_uart_regs *) + __va((((unsigned long)fpregs[4].which_io)<<32) | + (((unsigned long)fpregs[4].phys_addr))); + fhc->fhc_regs.tregs = (struct fhc_tod_regs *) + __va((((unsigned long)fpregs[5].which_io)<<32) | + (((unsigned long)fpregs[5].phys_addr))); + prom_printf("CENTRAL: FHC_REGS[%p %p %p %p %p %p]\n", + fhc->fhc_regs.pregs, fhc->fhc_regs.ireg, + fhc->fhc_regs.ffregs, fhc->fhc_regs.sregs, + fhc->fhc_regs.uregs, fhc->fhc_regs.tregs); + + prom_printf("CENTRAL: reading FHC_ID register... "); + err = fhc->fhc_regs.pregs->fhc_id; + prom_printf("VALUE[%x]\n", err); + printk("FHC Version[%x] PartID[%x] Manufacturer[%x]\n", + ((err & FHC_ID_VERS) >> 28), + ((err & FHC_ID_PARTID) >> 12), + ((err & FHC_ID_MANUF) >> 1)); + + return memory_start; +} diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/cpu.c linux/arch/sparc64/kernel/cpu.c --- v2.1.50/linux/arch/sparc64/kernel/cpu.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/cpu.c Sat Aug 16 09:51:08 1997 @@ -46,8 +46,13 @@ #define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) -char *sparc_cpu_type[NCPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" }; -char *sparc_fpu_type[NCPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" }; +#ifdef __SMP__ +char *sparc_cpu_type[NR_CPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" }; +char *sparc_fpu_type[NR_CPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" }; +#else +char *sparc_cpu_type[NR_CPUS] = { "cpu-oops", }; +char *sparc_fpu_type[NR_CPUS] = { "fpu-oops", }; +#endif unsigned int fsr_storage; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c --- v2.1.50/linux/arch/sparc64/kernel/devices.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/devices.c Sat Aug 16 09:51:08 1997 @@ -17,13 +17,14 @@ int linux_num_cpus = 0; extern void cpu_probe(void); +extern unsigned long central_probe(unsigned long); __initfunc(unsigned long device_scan(unsigned long mem_start)) { char node_str[128]; int nd, prom_node_cpu, thismid; - int cpu_nds[NCPUS]; /* One node for each cpu */ + int cpu_nds[NR_CPUS]; /* One node for each cpu */ int cpu_ctr = 0; prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str)); @@ -43,11 +44,14 @@ if(strcmp(node_str, "cpu") == 0) { cpu_nds[cpu_ctr] = scan; linux_cpus[cpu_ctr].prom_node = scan; - prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid)); + prom_getproperty(scan, "upa-portid", + (char *) &thismid, sizeof(thismid)); linux_cpus[cpu_ctr].mid = thismid; prom_printf("Found CPU %d \n", cpu_ctr, (unsigned) scan, thismid); + printk("Found CPU %d \n", + cpu_ctr, (unsigned) scan, thismid); cpu_ctr++; } }; @@ -62,5 +66,5 @@ linux_num_cpus = cpu_ctr; cpu_probe(); - return mem_start; + return central_probe(mem_start); } diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/dtlb_miss.S linux/arch/sparc64/kernel/dtlb_miss.S --- v2.1.50/linux/arch/sparc64/kernel/dtlb_miss.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/dtlb_miss.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: dtlb_miss.S,v 1.12 1997/06/26 12:47:08 jj Exp $ +/* $Id: dtlb_miss.S,v 1.13 1997/08/14 19:27:15 davem Exp $ * dtlb_miss.S: Data TLB miss code, this is included directly * into the trap table. * @@ -62,7 +62,7 @@ /*0x40*/ sllx %g1, 22, %g5 ! This is now physical page + PAGE_OFFSET /*0x44*/ brgez,pn %g5, 4f ! If >= 0, then walk down page tables /*0x48*/ sethi %uhi(KERN_HIGHBITS), %g1 ! Construct PTE ^ PAGE_OFFSET - /*0x4c*/ andcc %g3, 0x80, %g0 ! Slick trick... + /*0x4c*/ andcc %g3, 0x400, %g0 ! Slick trick... /*0x50*/ sllx %g1, 32, %g1 ! Move high bits up /*0x54*/ or %g1, (KERN_LOWBITS), %g1 ! Assume not IO /*0x58*/ bne,a,pn %icc, 5f ! Is it an IO page? diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/dtlb_prot.S linux/arch/sparc64/kernel/dtlb_prot.S --- v2.1.50/linux/arch/sparc64/kernel/dtlb_prot.S Sat May 24 09:10:23 1997 +++ linux/arch/sparc64/kernel/dtlb_prot.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: dtlb_prot.S,v 1.12 1997/05/18 10:04:43 davem Exp $ +/* $Id: dtlb_prot.S,v 1.14 1997/08/03 09:07:00 davem Exp $ * dtlb_prot.S: Data TLB protection code, this is included directly * into the trap table. * @@ -36,17 +36,17 @@ /* ICACHE line 3 */ /*0x40*/ add %g2, 7, %g5 ! Compute mask /*0x44*/ andn %g4, %g5, %g4 ! Mask page - /*0x48*/ or %g4, 0x10, %g4 ! 2ndary Context - /*0x4c*/ stxa %g0, [%g4] ASI_DMMU_DEMAP ! TLB flush page - /*0x50*/ membar #Sync ! Synchronize - /*0x54*/ stxa %g3, [%g1] ASI_PHYS_USE_EC ! Update sw PTE - /*0x58*/ stxa %g3, [%g0] ASI_DTLB_DATA_IN ! TLB load - /*0x5c*/ retry ! Trap return + /*0x48*/ mov TLB_SFSR, %g5 ! read SFSR + /*0x4c*/ ldxa [%g5] ASI_DMMU, %g5 ! from DMMU for + /*0x50*/ and %g5, 0x10, %g5 ! context bit + /*0x54*/ or %g4, %g5, %g4 ! for prot trap +1:/*0x58*/ stxa %g0, [%g4] ASI_DMMU_DEMAP ! TLB flush page + /*0x5c*/ membar #Sync ! Synchronize /* ICACHE line 4 */ - /*0x60*/ nop - /*0x64*/ nop - /*0x68*/ nop + /*0x60*/ stxa %g3, [%g1] ASI_PHYS_USE_EC ! Update sw PTE + /*0x64*/ stxa %g3, [%g0] ASI_DTLB_DATA_IN ! TLB load + /*0x68*/ retry ! Trap return /*0x6c*/ nop /*0x70*/ nop /*0x74*/ nop diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.1.50/linux/arch/sparc64/kernel/ebus.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/ebus.c Sat Aug 16 09:51:08 1997 @@ -0,0 +1,169 @@ +/* $Id: ebus.c,v 1.2 1997/08/15 06:44:13 davem Exp $ + * ebus.c: PCI to EBus bridge device. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct linux_ebus *ebus_chain = 0; + +static char lbuf[128]; + +extern void prom_ebus_ranges_init(struct linux_ebus *); + +#ifdef CONFIG_SUN_OPENPROMIO +extern int openprom_init(void); +#endif +#ifdef CONFIG_SUN_MOSTEK_RTC +extern int rtc_init(void); +#endif +#ifdef CONFIG_SPARCAUDIO +extern int sparcaudio_init(void); +#endif +#ifdef CONFIG_SUN_AUXIO +extern void auxio_probe(void); +#endif + +__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) +{ + int irqs[PROMINTR_MAX]; + 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 *)dev->regs, + sizeof(dev->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_registers = len / sizeof(struct linux_prom_registers); + + prom_apply_ebus_ranges(dev->parent, dev->regs, dev->num_registers); +#if 0 /* XXX No longer exists/needed in new framework... */ + prom_apply_pbm_ranges(dev->parent->parent, dev->regs, + dev->num_registers); +#endif + + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { + dev->irqs[0].pri = 0; + dev->num_irqs = 0; + } else { + dev->num_irqs = len / sizeof(irqs[0]); + for (i = 0; i < dev->num_irqs; i++) + dev->irqs[i].pri = irqs[i]; + } + + printk("Found '%s' at %x.%08x", dev->prom_name, + dev->regs[0].which_io, dev->regs[0].phys_addr); + if (dev->num_irqs) { + printk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); + for (i = 0; i < dev->num_irqs; i++) + printk(" %03x", dev->irqs[i].pri); + } + printk("\n"); +} + +__initfunc(unsigned long ebus_init(unsigned long memory_start, + unsigned long memory_end)) +{ + struct linux_ebus_device *dev; + struct linux_ebus *ebus; + int nd, ebusnd, topnd; + int num_ebus = 0; + +#ifndef CONFIG_PCI + return memory_start; +#endif + + memory_start = ((memory_start + 7) & (~7)); + + topnd = psycho_root->pbm_B.prom_node; + if (!topnd) + return memory_start; + + ebusnd = prom_searchsiblings(prom_getchild(topnd), "ebus"); + if (ebusnd == 0) { + printk("EBUS: No EBUS's found.\n"); + return memory_start; + } + + ebus_chain = ebus = (struct linux_ebus *)memory_start; + memory_start += sizeof(struct linux_ebus); + ebus->next = 0; + + while (ebusnd) { + printk("ebus%d: ", num_ebus); + + prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); + ebus->prom_node = ebusnd; + strcpy(ebus->prom_name, lbuf); + ebus->parent = &psycho_root->pbm_B; + + prom_ebus_ranges_init(ebus); + + nd = prom_getchild(ebusnd); + ebus->devices = (struct linux_ebus_device *)memory_start; + memory_start += sizeof(struct linux_ebus_device); + + dev = ebus->devices; + dev->next = 0; + dev->parent = ebus; + fill_ebus_device(nd, dev); + + while ((nd = prom_getsibling(nd))) { + dev->next = (struct linux_ebus_device *)memory_start; + memory_start += sizeof(struct linux_ebus_device); + + dev = dev->next; + dev->next = 0; + dev->parent = ebus; + fill_ebus_device(nd, dev); + } + + ebusnd = prom_searchsiblings(prom_getsibling(ebusnd), "ebus"); + ++num_ebus; + } + +#ifdef CONFIG_SUN_OPENPROMIO + openprom_init(); +#endif +#ifdef CONFIG_SUN_MOSTEK_RTC + rtc_init(); +#endif +#ifdef CONFIG_SPARCAUDIO + sparcaudio_init(); +#endif +#ifdef CONFIG_SUN_BPP + bpp_init(); +#endif +#ifdef CONFIG_SUN_AUXIO + if (sparc_cpu_model == sun4u) + auxio_probe(); +#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 + return memory_start; +} diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.1.50/linux/arch/sparc64/kernel/entry.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/entry.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.51 1997/07/24 12:15:04 davem Exp $ +/* $Id: entry.S,v 1.61 1997/08/15 06:44:16 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -50,41 +50,39 @@ bgu,a,pn %icc, winfix_trampoline rdpr %tpc, %g3 + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 b,pt %xcc, 1f mov 1, %o2 + .align 32 sparc64_dtlb_refbit_catch: srlx %g5, 9, %g4 and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 - cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) be,a,pt %xcc, 2f mov 1, %g4 wr %g0, ASI_DMMU, %asi rdpr %pstate, %g1 wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + rdpr %tl, %g3 ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 - cmp %g3, 1 bgu,pn %icc, winfix_trampoline rdpr %tpc, %g3 + sethi %hi(109f), %g7 b,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 + clr %o2 1: srlx %l5, PAGE_SHIFT, %o1 add %sp, STACK_BIAS + REGWIN_SZ, %o0 - call do_sparc64_fault sllx %o1, PAGE_SHIFT, %o1 b,pt %xcc, rtrap clr %l6 - nop - nop - nop - nop - + .align 32 sparc64_itlb_refbit_catch: srlx %g5, 9, %g4 and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 @@ -95,17 +93,21 @@ wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate rdpr %tpc, %g5 + sethi %hi(109f), %g7 b,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 b,pt %xcc, 1b clr %o2 + + .align 32 2: sllx %g4, 63, %g4 ! _PAGE_VALID or %g5, _PAGE_ACCESSED, %g5 or %g5, %g4, %g5 stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load retry + + .align 32 3: sllx %g4, 63, %g4 ! _PAGE_VALID or %g5, _PAGE_ACCESSED, %g5 or %g5, %g4, %g5 @@ -172,6 +174,7 @@ or %g2, %lo((((PAGE_SIZE<<1)-((64*4)+(2*8))) & ~(64 - 1))), %g2 add %g6, %g2, %g2 mov SECONDARY_CONTEXT, %g3 + ldxa [%g3] ASI_DMMU, %g7 stxa %g0, [%g3] ASI_DMMU flush %g2 wr %g0, ASI_BLK_S, %asi ! grrr, where is ASI_BLK_NUCLEUS 8-( @@ -182,9 +185,12 @@ ldda [%g2 + 0x080] %asi, %f32 ldda [%g2 + 0x0c0] %asi, %f48 ldx [%g2 + 0x100], %fsr - ldx [%g2 + 0x108], %g2 + ldx [%g2 + 0x108], %g4 membar #Sync - wr %g2, 0, %gsr + wr %g4, 0, %gsr + + stxa %g7, [%g3] ASI_DMMU + flush %g2 fpdis_exit: rdpr %tstate, %g3 sethi %hi(TSTATE_PEF), %g4 @@ -192,10 +198,7 @@ wrpr %g3, %tstate retry -#ifdef __SMP__ - /* Note check out head.h, this code isn't even used for UP, - * for SMP things will be different. In particular the data - * registers for cross calls will be: + /* The registers for cross calls will be: * * DATA 0: [low 32-bits] Address of function to call, jmp to this * [high 32-bits] MMU Context Argument 0, place in %g5 @@ -205,11 +208,17 @@ * With this method we can do most of the cross-call tlb/cache * flushing very quickly. */ + .data + .align 8 + .globl ivec_spurious_cookie +ivec_spurious_cookie: .xword 0 + + .text .align 32 - .globl do_ivec, do_ivec_return + .globl do_ivec do_ivec: - ldxa [%g0] ASI_INTR_RECEIVE, %g1 - andcc %g1, 0x20, %g0 + ldxa [%g0] ASI_INTR_RECEIVE, %g5 + andcc %g5, 0x20, %g0 be,pn %xcc, do_ivec_return mov 0x40, %g2 @@ -230,32 +239,35 @@ * which is completely harmless. */ wr %g2, 0x0, %set_softint - do_ivec_return: - /* Acknowledge the UPA */ stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync retry do_ivec_xcall: srlx %g3, 32, %g5 add %g2, 0x10, %g2 - sra %g3, 0, %g3 + srl %g3, 0, %g3 ldxa [%g2] ASI_UDB_INTR_R, %g6 add %g2, 0x10, %g2 + ldxa [%g2] ASI_UDB_INTR_R, %g7 + stxa %g0, [%g0] ASI_INTR_RECEIVE jmpl %g3, %g0 - ldxa [%g2] ASI_UDB_INTR_R, %g7 + membar #Sync do_ivec_spurious: + srl %g3, 3, %g3 + sethi %hi(ivec_spurious_cookie), %g2 + stx %g3, [%g2 + %lo(ivec_spurious_cookie)] stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync - rdpr %pstate, %g1 - wrpr %g1, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pstate, %g5 + wrpr %g5, PSTATE_IG | PSTATE_AG, %pstate + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 call report_spurious_ivec add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,pt %xcc, rtrap clr %l6 -#endif /* __SMP__ */ .globl getcc, setcc getcc: @@ -359,8 +371,9 @@ floppy_dosoftint: rdpr %pil, %g2 wrpr %g0, 15, %pil + sethi %hi(109f), %g7 b,pt %xcc, etrap_irq - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 mov 11, %o0 mov 0, %o1 @@ -386,8 +399,9 @@ cmp %g3, 1 bgu,a,pn %icc, winfix_mna rdpr %tpc, %g3 + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 call mem_address_unaligned add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,pt %xcc, rtrap @@ -573,14 +587,8 @@ sys_vfork: mov SIGCHLD, %o0 clr %o1 sys_clone: mov %o7, %l5 -/*???*/ save %sp, -REGWIN_SZ, %sp - flushw -/*???*/ restore %g0, %g0, %g0 - rdpr %cwp, %o4 add %sp, STACK_BIAS + REGWIN_SZ, %o2 - movrz %o1, %fp, %o1 - stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0] call do_fork mov %l5, %o7 #ifdef __SMP__ @@ -611,9 +619,9 @@ cmp %g1, NR_SYSCALLS ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI mov %i0, %o0 ! IEU0 - sll %g1, 3, %l4 ! IEU0 Group + sll %g1, 2, %l4 ! IEU0 Group mov %i1, %o1 ! IEU1 - ldx [%l7 + %l4], %l7 ! Load + lduw [%l7 + %l4], %l7 ! Load syscall_is_too_hard: mov %i2, %o2 ! IEU0 Group ldx [%curptr + AOFF_task_flags], %l5 ! Load diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S --- v2.1.50/linux/arch/sparc64/kernel/etrap.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/etrap.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.30 1997/06/30 10:31:37 jj Exp $ +/* $Id: etrap.S,v 1.34 1997/08/08 08:33:40 jj Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -16,6 +16,11 @@ #define TASK_REGOFF ((((PAGE_SIZE<<1)-FPUREG_SZ)&~(64-1)) - \ TRACEREG_SZ-REGWIN_SZ) +/* + * On entry, %g7 is return address - 0x4. + * %g4 and %g5 will be preserved %l4 and %l5 respectively. + */ + .text .align 32 .globl etrap, etrap_irq, etraptl1 @@ -111,18 +116,23 @@ membar #Sync sub %g2, (TRACEREG_SZ + REGWIN_SZ), %g2 -2: b,pt %xcc, etrap_after_fpu +2: bne,pn %xcc, etrap_after_fpu wr %g0, 0, %fprs -3: /* Because Ultra lacks ASI_BLK_NUCLEUS a hack has to take place. */ - mov SECONDARY_CONTEXT, %g3 + ld [%g6 + AOFF_task_tss + AOFF_thread_ctx], %g3 + wr %g0, ASI_DMMU, %asi + nop + stxa %g3, [%g0 + SECONDARY_CONTEXT] %asi + flush %g2 + + b,pt %xcc, etrap_after_fpu + nop +3: mov SECONDARY_CONTEXT, %g3 stxa %g0, [%g3] ASI_DMMU flush %g2 wr %g0, ASI_BLK_S, %asi - nop - b,pt %xcc, 1b mov FPRS_FEF, %g3 - nop + etraptl1: rdpr %tstate, %g1 sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ba,pt %xcc, etrap_maybe_fpu diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S --- v2.1.50/linux/arch/sparc64/kernel/head.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/head.S Sat Aug 16 09:51:08 1997 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.43 1997/07/07 03:05:25 davem Exp $ +/* $Id: head.S,v 1.46 1997/08/08 08:33:30 jj Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -21,6 +21,7 @@ #include #include #include +#include /* This section from from _start to sparc64_boot_end should fit into * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space @@ -89,6 +90,28 @@ */ wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate +#ifdef __SMP__ + /* Ugly but necessary... */ + sethi %hi(KERNBASE), %g7 + sethi %hi(sparc64_cpu_startup), %g5 + or %g5, %lo(sparc64_cpu_startup), %g5 + sub %g5, %g7, %g5 + sethi %hi(sparc64_cpu_startup_end), %g6 + or %g6, %lo(sparc64_cpu_startup_end), %g6 + sub %g6, %g7, %g6 + sethi %hi(smp_trampoline), %g3 + or %g3, %lo(smp_trampoline), %g3 + sub %g3, %g7, %g3 +1: ldx [%g5], %g1 + stx %g1, [%g3] + membar #StoreStore + flush %g3 + add %g5, 8, %g5 + cmp %g5, %g6 + blu,pt %xcc, 1b + add %g3, 8, %g3 +#endif + create_mappings: /* %g5 holds the tlb data */ sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 @@ -340,7 +363,7 @@ mov 0x40, %g2 /* INTR data 0 register */ /* Ok, we're done setting up all the state our trap mechanims needs, - * now get back into normal globals and let the PROM know what it up. + * now get back into normal globals and let the PROM know what is up. */ wrpr %g0, %g0, %wstate wrpr %o1, PSTATE_IE, %pstate @@ -374,6 +397,7 @@ ! 0x0000000000408000 #include "ttable.S" +#include "systbls.S" #include "etrap.S" #include "rtrap.S" #include "winfixup.S" diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.1.50/linux/arch/sparc64/kernel/ioctl32.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/ioctl32.c Sat Aug 16 10:00:14 1997 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.14 1997/07/17 06:21:12 davem Exp $ +/* $Id: ioctl32.c,v 1.13 1997/07/17 02:20:38 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ioport.c linux/arch/sparc64/kernel/ioport.c --- v2.1.50/linux/arch/sparc64/kernel/ioport.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/ioport.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: ioport.c,v 1.11 1997/07/22 06:14:04 davem Exp $ +/* $Id: ioport.c,v 1.12 1997/08/08 05:07:02 davem Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -45,7 +45,7 @@ u32 bus_type, int rdonly) { unsigned long vaddr, base_address; - unsigned long addr = ((unsigned long) address) + (((unsigned long) bus_type) << 32); + unsigned long addr = ((unsigned long)address) + (((unsigned long)bus_type)<<32); unsigned long offset = (addr & (~PAGE_MASK)); if (virtual) { @@ -64,7 +64,12 @@ /* Tell Linux resource manager about the mapping */ request_region ((vaddr | offset), len, name); } else { - return __va(addr); + unsigned long vaddr = (unsigned long) __va(addr); + + if(!check_region(vaddr, len)) + request_region(vaddr, len, name); + + return (void *) vaddr; } base_address = vaddr; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.1.50/linux/arch/sparc64/kernel/irq.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/irq.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.19 1997/07/24 12:15:04 davem Exp $ +/* $Id: irq.c,v 1.34 1997/08/15 06:44:18 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -28,8 +28,18 @@ #include #include +#ifdef CONFIG_PCI +#include +#include +#endif + /* Internal flag, should not be visible elsewhere at all. */ -#define SA_SYSIO_MASKED 0x100 +#define SA_IMAP_MASKED 0x100 + +#ifdef __SMP__ +void distribute_irqs(void); +static int irqs_have_been_distributed = 0; +#endif /* UPA nodes send interrupt packet to UltraSparc with first data reg value * low 5 bits holding the IRQ identifier being delivered. We must translate @@ -37,10 +47,39 @@ * make things even more swift we store the complete mask here. */ -#define NUM_IVECS 2048 /* XXX may need more on sunfire/wildfire */ +#define NUM_HARD_IVECS 2048 +#define NUM_IVECS (NUM_HARD_IVECS + 64) /* For SMP IRQ distribution alg. */ unsigned long ivector_to_mask[NUM_IVECS]; +struct ino_bucket { + struct ino_bucket *next; + unsigned int ino; + unsigned int *imap; + unsigned int *iclr; +}; + +#define INO_HASHSZ (NUM_HARD_IVECS >> 2) +#define NUM_INO_STATIC 4 +static struct ino_bucket *ino_hash[INO_HASHSZ] = { NULL, }; +static struct ino_bucket static_ino_buckets[NUM_INO_STATIC]; +static int static_ino_bucket_count = 0; + +static inline struct ino_bucket *__ino_lookup(unsigned int hash, unsigned int ino) +{ + struct ino_bucket *ret = ino_hash[hash]; + + for(ret = ino_hash[hash]; ret && ret->ino != ino; ret = ret->next) + ; + + return ret; +} + +static inline struct ino_bucket *ino_lookup(unsigned int ino) +{ + return __ino_lookup((ino & (INO_HASHSZ - 1)), ino); +} + /* This is based upon code in the 32-bit Sparc kernel written mostly by * David Redman (djhr@tadpole.co.uk). */ @@ -76,12 +115,12 @@ return len; } -/* INO number to Sparc PIL level. */ -unsigned char ino_to_pil[] = { - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 0 */ - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 1 */ - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 2 */ - 0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 3 */ +/* SBUS SYSIO INO number to Sparc PIL level. */ +unsigned char sysio_ino_to_pil[] = { + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 0 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 1 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 2 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 3 */ 3, /* Onboard SCSI */ 5, /* Onboard Ethernet */ /*XXX*/ 8, /* Onboard BPP */ @@ -112,7 +151,7 @@ */ #define offset(x) ((unsigned long)(&(((struct sysio_regs *)0)->x))) #define bogon ((unsigned long) -1) -static unsigned long irq_offsets[] = { +static unsigned long sysio_irq_offsets[] = { /* SBUS Slot 0 --> 3, level 1 --> 7 */ offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0), offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0), @@ -134,29 +173,29 @@ #undef bogon -#define NUM_IRQ_ENTRIES (sizeof(irq_offsets) / sizeof(irq_offsets[0])) +#define NUM_SYSIO_OFFSETS (sizeof(sysio_irq_offsets) / sizeof(sysio_irq_offsets[0])) -/* Convert an "interrupts" property IRQ level to an SBUS/SYSIO - * Interrupt Mapping register pointer, or NULL if none exists. +/* XXX Old compatability cruft, get rid of me when all drivers have been + * XXX converted to dcookie registry calls... -DaveM */ -static unsigned int *irq_to_imap(unsigned int irq) +static unsigned int *sysio_irq_to_imap(unsigned int irq) { unsigned long offset; struct sysio_regs *sregs; if((irq == 14) || - (irq >= NUM_IRQ_ENTRIES) || - ((offset = irq_offsets[irq]) == ((unsigned long)-1))) + (irq >= NUM_SYSIO_OFFSETS) || + ((offset = sysio_irq_offsets[irq]) == ((unsigned long)-1))) return NULL; sregs = SBus_chain->iommu->sysio_regs; offset += ((unsigned long) sregs); - return ((unsigned int *)offset) + 1; + return ((unsigned int *)offset); } /* Convert Interrupt Mapping register pointer to assosciated - * Interrupt Clear register pointer. + * Interrupt Clear register pointer, SYSIO specific version. */ -static unsigned int *imap_to_iclr(unsigned int *imap) +static unsigned int *sysio_imap_to_iclr(unsigned int *imap) { unsigned long diff; @@ -166,32 +205,63 @@ #undef offset -/* For non-SBUS IRQ's we do nothing, else we must enable them in the - * appropriate SYSIO interrupt map registers. +#ifdef CONFIG_PCI +/* PCI PSYCHO INO number to Sparc PIL level. */ +unsigned char psycho_ino_to_pil[] = { + 7, 5, 5, 2, /* PCI A slot 0 Int A, B, C, D */ + 7, 5, 5, 2, /* PCI A slot 1 Int A, B, C, D */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 6, 4, 3, 1, /* PCI B slot 0 Int A, B, C, D */ + 6, 4, 3, 1, /* PCI B slot 1 Int A, B, C, D */ + 6, 4, 3, 1, /* PCI B slot 2 Int A, B, C, D */ + 6, 4, 3, 1, /* PCI B slot 3 Int A, B, C, D */ + 3, /* SCSI */ + 3, /* Ethernet */ + 2, /* Parallel Port */ + 8, /* Audio Record */ + 7, /* Audio Playback */ + 8, /* PowerFail */ + 7, /* Keyboard/Mouse/Serial */ + 8, /* Floppy */ + 2, /* Spare Hardware */ + 4, /* Keyboard */ + 4, /* Mouse */ + 7, /* Serial */ + 6, /* Timer 0 */ + 6, /* Timer 1 */ + 8, /* Uncorrectable ECC */ + 8, /* Correctable ECC */ + 8, /* PCI Bus A Error */ + 7, /* PCI Bus B Error */ + 1, /* Power Management */ +}; + +/* INO number to IMAP register offset for PSYCHO external IRQ's. */ -void enable_irq(unsigned int irq) +#define psycho_offset(x) ((unsigned long)(&(((struct psycho_regs *)0)->x))) + +#define psycho_imap_offset(ino) \ + ((ino & 0x20) ? (psycho_offset(imap_scsi) + (((ino) & 0x1f) << 3)) : \ + (psycho_offset(imap_a_slot0) + (((ino) & 0x3c) << 1))) + +#define psycho_iclr_offset(ino) \ + ((ino & 0x20) ? (psycho_offset(iclr_scsi) + (((ino) & 0x1f) << 3)) : \ + (psycho_offset(iclr_a_slot0[0]) + (((ino) & 0x1f) << 3))) + +#endif + +/* Now these are always passed a true fully specified sun4u INO. */ +void enable_irq(unsigned int ino) { + struct ino_bucket *bucket = ino_lookup(ino); unsigned long tid; unsigned int *imap; - /* If this is for the tick interrupt, just ignore, note - * that this is the one and only locally generated interrupt - * source, all others come from external sources (essentially - * any UPA device which is an interruptor). (actually, on - * second thought Ultra can generate local interrupts for - * async memory errors and we may setup handlers for those - * at some point as well) - * - * XXX See commentary below in request_irq() this assumption - * XXX is broken and needs to be fixed. - */ - if(irq == 14) + if(!bucket) return; - /* Check for bogons. */ - imap = irq_to_imap(irq); - if(imap == NULL) - goto do_the_stb_watoosi; + imap = bucket->imap; /* We send it to our UPA MID, for SMP this will be different. */ __asm__ __volatile__("ldxa [%%g0] %1, %0" : "=r" (tid) : "i" (ASI_UPA_CONFIG)); @@ -202,28 +272,22 @@ * Register, the hardware just mirrors that value here. * However for Graphics and UPA Slave devices the full * SYSIO_IMAP_INR field can be set by the programmer here. - * (XXX we will have to handle those for FFB etc. XXX) + * + * Things like FFB can now be handled via the dcookie mechanism. */ *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID); - return; - -do_the_stb_watoosi: - printk("Cannot enable irq(%d), doing the \"STB Watoosi\" instead.", irq); - panic("Trying to enable bogon IRQ"); } -void disable_irq(unsigned int irq) +/* This now gets passed true ino's as well. */ +void disable_irq(unsigned int ino) { + struct ino_bucket *bucket = ino_lookup(ino); unsigned int *imap; - /* XXX Grrr, I know this is broken... */ - if(irq == 14) + if(!bucket) return; - /* Check for bogons. */ - imap = irq_to_imap(irq); - if(imap == NULL) - goto do_the_stb_watoosi; + imap = bucket->imap; /* NOTE: We do not want to futz with the IRQ clear registers * and move the state to IDLE, the SCSI code does call @@ -231,34 +295,218 @@ * SCSI adapter driver code. Thus we'd lose interrupts. */ *imap &= ~(SYSIO_IMAP_VALID); - return; +} + +static void get_irq_translations(int *cpu_irq, int *ivindex_fixup, + unsigned int **imap, unsigned int **iclr, + void *busp, unsigned long flags, + unsigned int irq) +{ + if(*cpu_irq != -1 && *imap != NULL && *iclr != NULL) + return; + + if(*cpu_irq != -1 || *imap != NULL || *iclr != NULL || busp == NULL) { + printk("get_irq_translations: Partial specification, this is bad.\n"); + printk("get_irq_translations: cpu_irq[%d] imap[%p] iclr[%p] busp[%p]\n", + *cpu_irq, *imap, *iclr, busp); + panic("Bad IRQ translations..."); + } + + if(SA_BUS(flags) == SA_SBUS) { + struct linux_sbus *sbusp = busp; + struct sysio_regs *sregs = sbusp->iommu->sysio_regs; + unsigned long offset; + + *cpu_irq = sysio_ino_to_pil[irq]; + if(*cpu_irq == 0) { + printk("get_irq_translations: Bad SYSIO INO[%x]\n", irq); + panic("Bad SYSIO IRQ translations..."); + } + offset = sysio_irq_offsets[irq]; + if(offset == ((unsigned long)-1)) { + printk("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", + irq, *cpu_irq); + panic("BAD SYSIO IRQ offset..."); + } + offset += ((unsigned long)sregs); + *imap = ((unsigned int *)offset); + + /* SYSIO inconsistancy. For external SLOTS, we have to select + * the right ICLR register based upon the lower SBUS irq level + * bits. + */ + if(irq >= 0x20) { + *iclr = sysio_imap_to_iclr(*imap); + } else { + unsigned long iclraddr; + int sbus_slot = (irq & 0x18)>>3; + int sbus_level = irq & 0x7; + + switch(sbus_slot) { + case 0: + *iclr = &sregs->iclr_slot0; + break; + case 1: + *iclr = &sregs->iclr_slot1; + break; + case 2: + *iclr = &sregs->iclr_slot2; + break; + case 3: + *iclr = &sregs->iclr_slot3; + break; + }; + + iclraddr = (unsigned long) *iclr; + iclraddr += ((sbus_level - 1) * 8); + *iclr = (unsigned int *) iclraddr; + +#if 0 /* DEBUGGING */ + printk("SYSIO_FIXUP: slot[%x] level[%x] iclr[%p] ", + sbus_slot, sbus_level, *iclr); +#endif -do_the_stb_watoosi: - printk("Cannot disable irq(%d), doing the \"STB Watoosi\" instead.", irq); - panic("Trying to enable bogon IRQ"); + /* Also, make sure this is accounted for in ivindex + * computations done by the caller. + */ + *ivindex_fixup = sbus_level; + } + return; + } +#ifdef CONFIG_PCI + if(SA_BUS(flags) == SA_PCI) { + struct pci_bus *pbusp = busp; + struct linux_pbm_info *pbm = pbusp->sysdata; + struct psycho_regs *pregs = pbm->parent->psycho_regs; + unsigned long offset; + + *cpu_irq = psycho_ino_to_pil[irq & 0x3f]; + if(*cpu_irq == 0) { + printk("get_irq_translations: Bad PSYCHO INO[%x]\n", irq); + panic("Bad PSYCHO IRQ translations..."); + } + offset = psycho_imap_offset(irq); + if(offset == ((unsigned long)-1)) { + printk("get_irq_translations: Bad PSYCHO INO[%x] cpu[%d]\n", + irq, *cpu_irq); + panic("Bad PSYCHO IRQ offset..."); + } + offset += ((unsigned long)pregs); + *imap = ((unsigned int *)offset) + 1; + *iclr = (unsigned int *) + (((unsigned long)pregs) + psycho_imap_offset(irq)); + return; + } +#endif +#if 0 /* XXX More to do before we can use this. -DaveM */ + if(SA_BUS(flags) == SA_FHC) { + struct fhc_bus *fbusp = busp; + struct fhc_regs *fregs = fbusp->regs; + unsigned long offset; + + *cpu_irq = fhc_ino_to_pil[irq]; + if(*cpu_irq == 0) { + printk("get_irq_translations: Bad FHC INO[%x]\n", irq); + panic("Bad FHC IRQ translations..."); + } + offset = fhc_irq_offset[*cpu_irq]; + if(offset == ((unsigned long)-1)) { + printk("get_irq_translations: Bad FHC INO[%x] cpu[%d]\n", + irq, *cpu_irq); + panic("Bad FHC IRQ offset..."); + } + offset += ((unsigned long)pregs); + *imap = (((unsigned int *)offset)+1); + *iclr = fhc_imap_to_iclr(*imap); + return; + } +#endif + printk("get_irq_translations: IRQ register for unknown bus type.\n"); + printk("get_irq_translations: BUS[%lx] IRQ[%x]\n", + SA_BUS(flags), irq); + panic("Bad IRQ bus type..."); +} + +/* Once added, they are never removed. */ +static struct ino_bucket *add_ino_hash(unsigned int ivindex, + unsigned int *imap, unsigned int *iclr, + unsigned long flags) +{ + struct ino_bucket *new = NULL, **hashp; + unsigned int hash = (ivindex & (INO_HASHSZ - 1)); + + new = __ino_lookup(hash, ivindex); + if(new) + return new; + if(flags & SA_STATIC_ALLOC) { + if(static_ino_bucket_count < NUM_INO_STATIC) + new = &static_ino_buckets[static_ino_bucket_count++]; + else + printk("Request for ino bucket SA_STATIC_ALLOC failed " + "using kmalloc\n"); + } + if(new == NULL) + new = kmalloc(sizeof(struct ino_bucket), GFP_KERNEL); + if(new) { + hashp = &ino_hash[hash]; + new->imap = imap; + new->iclr = iclr; + new->ino = ivindex; + new->next = *hashp; + *hashp = new; + } + return new; } int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char *name, void *dev_cookie) + unsigned long irqflags, const char *name, void *dev_id) { struct irqaction *action, *tmp = NULL; + struct devid_cookie *dcookie = NULL; + struct ino_bucket *bucket = NULL; unsigned long flags; - unsigned int cpu_irq, *imap, *iclr; + unsigned int *imap, *iclr; + void *bus_id = NULL; + int ivindex, ivindex_fixup, cpu_irq = -1; - /* XXX This really is not the way to do it, the "right way" - * XXX is to have drivers set SA_SBUS or something like that - * XXX in irqflags and we base our decision here on whether - * XXX that flag bit is set or not. - */ - if(irq == 14) - cpu_irq = irq; - else - cpu_irq = ino_to_pil[irq]; - if(!handler) return -EINVAL; - imap = irq_to_imap(irq); + imap = iclr = NULL; + + ivindex_fixup = 0; + if(irqflags & SA_DCOOKIE) { + if(!dev_id) { + printk("request_irq: SA_DCOOKIE but dev_id is NULL!\n"); + panic("Bogus irq registry."); + } + dcookie = dev_id; + dev_id = dcookie->real_dev_id; + cpu_irq = dcookie->pil; + imap = dcookie->imap; + iclr = dcookie->iclr; + bus_id = dcookie->bus_cookie; + get_irq_translations(&cpu_irq, &ivindex_fixup, &imap, + &iclr, bus_id, irqflags, irq); + } else { + /* XXX NOTE: This code is maintained for compatability until I can + * XXX verify that all drivers sparc64 will use are updated + * XXX to use the new IRQ registry dcookie interface. -DaveM + */ + if(irq == 14) + cpu_irq = irq; + else + cpu_irq = sysio_ino_to_pil[irq]; + imap = sysio_irq_to_imap(irq); + if(!imap) { + printk("request_irq: BAD, null imap for old style " + "irq registry IRQ[%x].\n", irq); + panic("Bad IRQ registery..."); + } + iclr = sysio_imap_to_iclr(imap); + } + ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); + ivindex += ivindex_fixup; action = *(cpu_irq + irq_action); if(action) { @@ -297,52 +545,61 @@ return -ENOMEM; } - if(imap) { - int ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); + bucket = add_ino_hash(ivindex, imap, iclr, irqflags); + if(!bucket) { + kfree(action); + restore_flags(flags); + return -ENOMEM; + } - ivector_to_mask[ivindex] = (1<mask = (unsigned long) iclr; - irqflags |= SA_SYSIO_MASKED; - } else { - action->mask = 0; + ivector_to_mask[ivindex] = (1 << cpu_irq); + + if(dcookie) { + dcookie->ret_ino = ivindex; + dcookie->ret_pil = cpu_irq; } + action->mask = (unsigned long) bucket; action->handler = handler; - action->flags = irqflags; + action->flags = irqflags | SA_IMAP_MASKED; action->name = name; action->next = NULL; - action->dev_id = dev_cookie; + action->dev_id = dev_id; if(tmp) tmp->next = action; else *(cpu_irq + irq_action) = action; - enable_irq(irq); + enable_irq(ivindex); restore_flags(flags); +#ifdef __SMP__ + if(irqs_have_been_distributed) + distribute_irqs(); +#endif return 0; } -void free_irq(unsigned int irq, void *dev_cookie) +void free_irq(unsigned int irq, void *dev_id) { struct irqaction *action; struct irqaction *tmp = NULL; unsigned long flags; unsigned int cpu_irq; + int ivindex = -1; if(irq == 14) cpu_irq = irq; else - cpu_irq = ino_to_pil[irq]; + cpu_irq = sysio_ino_to_pil[irq]; action = *(cpu_irq + irq_action); if(!action->handler) { printk("Freeing free IRQ %d\n", irq); return; } - if(dev_cookie) { + if(dev_id) { for( ; action; action = action->next) { - if(action->dev_id == dev_cookie) + if(action->dev_id == dev_id) break; tmp = action; } @@ -351,7 +608,7 @@ return; } } else if(action->flags & SA_SHIRQ) { - printk("Trying to free shared IRQ %d with NULL device cookie\n", irq); + printk("Trying to free shared IRQ %d with NULL device ID\n", irq); return; } @@ -367,29 +624,37 @@ else *(cpu_irq + irq_action) = action->next; - if(action->flags & SA_SYSIO_MASKED) { - unsigned int *imap = irq_to_imap(irq); - if(imap != NULL) - ivector_to_mask[*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)] = 0; + if(action->flags & SA_IMAP_MASKED) { + struct ino_bucket *bucket = (struct ino_bucket *)action->mask; + unsigned int *imap = bucket->imap; + + if(imap != NULL) { + ivindex = bucket->ino; + ivector_to_mask[ivindex] = 0; + } else printk("free_irq: WHeee, SYSIO_MASKED yet no imap reg.\n"); } kfree(action); - if(!*(cpu_irq + irq_action)) - disable_irq(irq); + if(ivindex != -1) + disable_irq(ivindex); restore_flags(flags); } -/* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */ -unsigned int local_irq_count[NR_CPUS]; +/* Only uniprocessor needs this IRQ locking depth, on SMP it lives in the per-cpu + * structure for cache reasons. + */ +#ifndef __SMP__ +unsigned int local_irq_count; +#endif #ifndef __SMP__ int __sparc64_bh_counter = 0; -#define irq_enter(cpu, irq) (local_irq_count[cpu]++) -#define irq_exit(cpu, irq) (local_irq_count[cpu]--) +#define irq_enter(cpu, irq) (local_irq_count++) +#define irq_exit(cpu, irq) (local_irq_count--) #else @@ -407,18 +672,31 @@ /* Global IRQ locking depth. */ atomic_t global_irq_count = ATOMIC_INIT(0); -static inline void wait_on_irq(int cpu) +static unsigned long previous_irqholder; + +#undef INIT_STUCK +#define INIT_STUCK 100000000 + +#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; } + +static inline void wait_on_irq(int cpu, unsigned long where) { - int local_count = local_irq_count[cpu]; + int stuck = INIT_STUCK; + int local_count = local_irq_count; while(local_count != atomic_read(&global_irq_count)) { atomic_sub(local_count, &global_irq_count); spin_unlock(&global_irq_lock); for(;;) { + STUCK; + membar("#StoreLoad | #LoadLoad"); if (atomic_read(&global_irq_count)) continue; - if (*((unsigned char *)&global_irq_lock)) + if (*((volatile unsigned char *)&global_irq_lock)) continue; + membar("#LoadLoad | #LoadStore"); if (spin_trylock(&global_irq_lock)) break; } @@ -426,25 +704,41 @@ } } -static inline void get_irqlock(int cpu) +#undef INIT_STUCK +#define INIT_STUCK 10000000 + +#undef STUCK +#define STUCK \ +if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;} + +static inline void get_irqlock(int cpu, unsigned long where) { + int stuck = INIT_STUCK; + if (!spin_trylock(&global_irq_lock)) { + membar("#StoreLoad | #LoadLoad"); if ((unsigned char) cpu == global_irq_holder) return; do { - barrier(); + do { + STUCK; + membar("#LoadLoad"); + } while(*((volatile unsigned char *)&global_irq_lock)); } while (!spin_trylock(&global_irq_lock)); } - wait_on_irq(cpu); + wait_on_irq(cpu, where); global_irq_holder = cpu; + previous_irqholder = where; } void __global_cli(void) { int cpu = smp_processor_id(); + unsigned long where; + __asm__ __volatile__("mov %%i7, %0" : "=r" (where)); __cli(); - get_irqlock(cpu); + get_irqlock(cpu, where); } void __global_sti(void) @@ -453,11 +747,6 @@ __sti(); } -unsigned long __global_save_flags(void) -{ - return global_irq_holder == (unsigned char) smp_processor_id(); -} - void __global_restore_flags(unsigned long flags) { if (flags & 1) { @@ -472,15 +761,24 @@ } } +#undef INIT_STUCK +#define INIT_STUCK 200000000 + +#undef STUCK +#define STUCK \ +if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;} + void irq_enter(int cpu, int irq) { + int stuck = INIT_STUCK; + hardirq_enter(cpu); - barrier(); - while (*((unsigned char *)&global_irq_lock)) { + while (*((volatile unsigned char *)&global_irq_lock)) { if ((unsigned char) cpu == global_irq_holder) printk("irq_enter: Frosted Lucky Charms, " "they're magically delicious!\n"); - barrier(); + STUCK; + membar("#LoadLoad"); } } @@ -492,8 +790,7 @@ void synchronize_irq(void) { - int cpu = smp_processor_id(); - int local_count = local_irq_count[cpu]; + int local_count = local_irq_count; unsigned long flags; if (local_count != atomic_read(&global_irq_count)) { @@ -506,8 +803,10 @@ void report_spurious_ivec(struct pt_regs *regs) { - printk("IVEC: Spurious interrupt vector received at (%016lx)\n", - regs->tpc); + extern unsigned long ivec_spurious_cookie; + + printk("IVEC: Spurious interrupt vector (%016lx) received at (%016lx)\n", + ivec_spurious_cookie, regs->tpc); return; } @@ -547,13 +846,20 @@ irq_enter(cpu, irq); action = *(irq + irq_action); kstat.interrupts[irq]++; - do { - if(!action || !action->handler) - unexpected_irq(irq, 0, regs); - action->handler(irq, action->dev_id, regs); - if(action->flags & SA_SYSIO_MASKED) - *((unsigned int *)action->mask) = SYSIO_ICLR_IDLE; - } while((action = action->next) != NULL); + if(!action) { + unexpected_irq(irq, 0, regs); + } else { + do { + action->handler(irq, action->dev_id, regs); + if(action->flags & SA_IMAP_MASKED) { + struct ino_bucket *bucket = + (struct ino_bucket *)action->mask; + + *(bucket->iclr) = SYSIO_ICLR_IDLE; + membar("#MemIssue"); + } + } while((action = action->next) != NULL); + } irq_exit(cpu, irq); } @@ -567,7 +873,7 @@ irq_enter(cpu, irq); floppy_interrupt(irq, dev_cookie, regs); - if(action->flags & SA_SYSIO_MASKED) + if(action->flags & SA_IMAP_MASKED) *((unsigned int *)action->mask) = SYSIO_ICLR_IDLE; irq_exit(cpu, irq); } @@ -595,7 +901,7 @@ insns[0] = SPARC_BRANCH(((unsigned long) handler), ((unsigned long)&insns[0])); insns[1] = SPARC_NOP; - __asm__ __volatile__("flush %0" : : "r" (ttent)); + __asm__ __volatile__("membar #StoreStore; flush %0" : : "r" (ttent)); } int request_fast_irq(unsigned int irq, @@ -605,6 +911,7 @@ struct irqaction *action; unsigned long flags; unsigned int cpu_irq, *imap, *iclr; + int ivindex = -1; /* XXX This really is not the way to do it, the "right way" * XXX is to have drivers set SA_SBUS or something like that @@ -616,11 +923,11 @@ */ if(irq == 14) return -EINVAL; - cpu_irq = ino_to_pil[irq]; + cpu_irq = sysio_ino_to_pil[irq]; if(!handler) return -EINVAL; - imap = irq_to_imap(irq); + imap = sysio_irq_to_imap(irq); action = *(cpu_irq + irq_action); if(action) { if(action->flags & SA_SHIRQ) @@ -648,12 +955,12 @@ install_fast_irq(cpu_irq, handler); if(imap) { - int ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); - + ivindex = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)); ivector_to_mask[ivindex] = (1 << cpu_irq); - iclr = imap_to_iclr(imap); + iclr = sysio_imap_to_iclr(imap); action->mask = (unsigned long) iclr; - irqflags |= SA_SYSIO_MASKED; + irqflags |= SA_IMAP_MASKED; + add_ino_hash(ivindex, imap, iclr, irqflags); } else action->mask = 0; @@ -665,7 +972,9 @@ *(cpu_irq + irq_action) = action; - enable_irq(irq); + if(ivindex != -1) + enable_irq(ivindex); + restore_flags(flags); return 0; } @@ -675,31 +984,27 @@ */ unsigned long probe_irq_on(void) { - return 0; + return 0; } int probe_irq_off(unsigned long mask) { - return 0; + return 0; } struct sun5_timer *linux_timers = NULL; -/* This is called from sbus_init() to get the jiffies timer going. - * We need to call this after there exists a valid SBus_chain so - * that the IMAP/ICLR registers can be accessed. - * - * XXX That is because the whole startup sequence is broken. I will - * XXX fix it all up very soon. -DaveM - */ +/* This is gets the master level10 timer going. */ void init_timers(void (*cfunc)(int, void *, struct pt_regs *)) { struct linux_prom64_registers pregs[3]; + struct devid_cookie dcookie; + unsigned int *imap, *iclr; u32 pirqs[2]; int node, err; node = prom_finddevice("/counter-timer"); - if(node == 0) { + if(node == 0 || node == -1) { prom_printf("init_timers: Cannot find counter-timer PROM node.\n"); prom_halt(); } @@ -715,13 +1020,22 @@ prom_halt(); } linux_timers = (struct sun5_timer *) __va(pregs[0].phys_addr); + iclr = (((unsigned int *)__va(pregs[1].phys_addr))+1); + imap = (((unsigned int *)__va(pregs[2].phys_addr))+1); /* Shut it up first. */ linux_timers->limit0 = 0; /* Register IRQ handler. */ - err = request_irq(pirqs[0] & 0x3f, /* XXX Fix this for big Enterprise XXX */ - cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); + dcookie.real_dev_id = NULL; + dcookie.imap = imap; + dcookie.iclr = iclr; + dcookie.pil = 10; + dcookie.bus_cookie = NULL; + + err = request_irq(pirqs[0], cfunc, + (SA_DCOOKIE | SA_INTERRUPT | SA_STATIC_ALLOC), + "timer", &dcookie); if(err) { prom_printf("Serious problem, cannot register timer interrupt\n"); @@ -824,6 +1138,52 @@ prom_timers->limit0 = prom_limit0; prom_timers->count0 = 0; } + +#ifdef __SMP__ +/* Called from smp_commence, when we know how many cpus are in the system + * and can have device IRQ's directed at them. + */ +void distribute_irqs(void) +{ + unsigned long flags; + int cpu, level; + + printk("SMP: redistributing interrupts...\n"); + save_and_cli(flags); + cpu = 0; + for(level = 0; level < NR_IRQS; level++) { + struct irqaction *p = irq_action[level]; + + while(p) { + if(p->flags & SA_IMAP_MASKED) { + struct ino_bucket *bucket = (struct ino_bucket *)p->mask; + unsigned int *imap = bucket->imap; + unsigned int val; + unsigned long tid = linux_cpus[cpu].mid << 9; + + val = *imap; + *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID); + + printk("SMP: Redirecting IGN[%x] INO[%x] " + "to cpu %d [%s]\n", + (val & SYSIO_IMAP_IGN) >> 6, + (val & SYSIO_IMAP_INO), cpu, + p->name); + + cpu += 1; + while(!(cpu_present_map & (1UL << cpu))) { + cpu += 1; + if(cpu >= smp_num_cpus) + cpu = 0; + } + } + p = p->next; + } + } + restore_flags(flags); + irqs_have_been_distributed = 1; +} +#endif __initfunc(void init_IRQ(void)) { diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.1.50/linux/arch/sparc64/kernel/process.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/process.c Sat Aug 16 10:00:14 1997 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.31 1997/07/24 12:15:05 davem Exp $ +/* $Id: process.c,v 1.29 1997/07/17 02:20:40 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -27,18 +27,21 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include #include +#define PGTCACHE_HIGH_WATER 50 +#define PGTCACHE_LOW_WATER 25 + #ifndef __SMP__ /* @@ -53,6 +56,16 @@ current->priority = -100; current->counter = -100; for (;;) { + if(pgtable_cache_size > PGTCACHE_LOW_WATER) { + do { + if(pgd_quicklist) + free_page((unsigned long) get_pgd_fast()); + if(pmd_quicklist) + free_page((unsigned long) get_pmd_fast()); + if(pte_quicklist) + free_page((unsigned long) get_pte_fast()); + } while(pgtable_cache_size > PGTCACHE_HIGH_WATER); + } run_task_queue(&tq_scheduler); schedule(); } @@ -68,13 +81,26 @@ { current->priority = -100; while(1) { + if(pgtable_cache_size > PGTCACHE_LOW_WATER) { + do { + if(pgd_quicklist) + free_page((unsigned long) get_pgd_fast()); + if(pmd_quicklist) + free_page((unsigned long) get_pmd_fast()); + if(pte_quicklist) + free_page((unsigned long) get_pte_fast()); + } while(pgtable_cache_size > PGTCACHE_HIGH_WATER); + } if(tq_scheduler) { lock_kernel(); run_task_queue(&tq_scheduler); unlock_kernel(); } + barrier(); current->counter = -100; - schedule(); + if(resched_needed()) + schedule(); + barrier(); } } @@ -251,8 +277,20 @@ } while ((size -= sizeof(unsigned))); } -void show_regs(struct pt_regs * regs) +#ifdef __SMP__ +static spinlock_t regdump_lock = SPIN_LOCK_UNLOCKED; +#endif + +void __show_regs(struct pt_regs * regs) { +#ifdef __SMP__ + unsigned long flags; + + spin_lock_irqsave(®dump_lock, flags); + printk("CPU[%d]: local_irq_count[%ld] global_irq_count[%d]\n", + smp_processor_id(), local_irq_count, + atomic_read(&global_irq_count)); +#endif printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x\n", regs->tstate, regs->tpc, regs->tnpc, regs->y); printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n", @@ -268,6 +306,21 @@ regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], regs->u_regs[15]); show_regwindow(regs); +#ifdef __SMP__ + spin_unlock_irqrestore(®dump_lock, flags); +#endif +} + +void show_regs(struct pt_regs *regs) +{ + __show_regs(regs); +#ifdef __SMP__ + { + extern void smp_report_regs(void); + + smp_report_regs(); + } +#endif } void show_regs32(struct pt_regs32 *regs) @@ -337,12 +390,16 @@ /* Now, this task is no longer a kernel thread. */ current->tss.current_ds = USER_DS; if(current->tss.flags & SPARC_FLAG_KTHREAD) { + extern spinlock_t scheduler_lock; + current->tss.flags &= ~SPARC_FLAG_KTHREAD; /* exec_mmap() set context to NO_CONTEXT, here is * where we grab a new one. */ + spin_lock(&scheduler_lock); get_mmu_context(current); + spin_unlock(&scheduler_lock); } current->tss.ctx = current->mm->context & 0x1fff; spitfire_set_secondary_context (current->tss.ctx); @@ -437,10 +494,14 @@ struct reg_window *rwin = &tp->reg_window[window]; if(copy_to_user((char *)sp, rwin, winsize)) - do_exit(SIGILL); + goto barf; } while(window--); } current->tss.w_saved = 0; + return; +barf: + lock_kernel(); + do_exit(SIGILL); } /* Copy a Sparc thread. The fork() return value conventions @@ -483,7 +544,7 @@ p->tss.kpc = ((unsigned long) ret_from_syscall) - 0x8; #endif p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window)); - p->tss.cwp = regs->u_regs[UREG_G0]; + p->tss.cwp = (regs->tstate + 1) & TSTATE_CWP; if(regs->tstate & TSTATE_PRIV) { p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp; p->tss.flags |= SPARC_FLAG_KTHREAD; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c --- v2.1.50/linux/arch/sparc64/kernel/psycho.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/psycho.c Sat Aug 16 09:51:09 1997 @@ -0,0 +1,668 @@ +/* $Id: psycho.c,v 1.5 1997/08/15 06:44:18 davem Exp $ + * psycho.c: Ultra/AX U2P PCI controller support. + * + * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) + */ + +#include +#include +#include + +#include +#include /* for sanity check... */ + +#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 + +#include +#include +#include +#include + +#include +#include +#include +#include + +struct linux_psycho *psycho_root = NULL; + +/* This is used to make the scan_bus in the generic PCI code be + * a nop, as we need to control the actual bus probing sequence. + * After that we leave it on of course. + */ +static int pci_probe_enable = 0; + +static inline unsigned long long_align(unsigned long addr) +{ + return ((addr + (sizeof(unsigned long) - 1)) & + ~(sizeof(unsigned long) - 1)); +} + +extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm); + +unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end) +{ + struct linux_prom64_registers pr_regs[3]; + char namebuf[128]; + u32 portid; + int node; + + /* prom_printf("PSYCHO: Probing for controllers.\n"); */ + printk("PSYCHO: Probing for controllers.\n"); + + memory_start = long_align(memory_start); + node = prom_getchild(prom_root_node); + while((node = prom_searchsiblings(node, "pci")) != 0) { + struct linux_psycho *psycho = (struct linux_psycho *)memory_start; + struct linux_psycho *search; + struct linux_pbm_info *pbm = NULL; + u32 busrange[2]; + int err, is_pbm_a; + + portid = prom_getintdefault(node, "upa-portid", 0xff); + for(search = psycho_root; search; search = search->next) { + if(search->upa_portid == portid) { + psycho = search; + + /* This represents _this_ instance, so it's + * which ever one does _not_ have the prom node + * info filled in yet. + */ + is_pbm_a = (psycho->pbm_A.prom_node == 0); + goto other_pbm; + } + } + + memory_start = long_align(memory_start + sizeof(struct linux_psycho)); + + memset(psycho, 0, sizeof(*psycho)); + + psycho->next = psycho_root; + psycho_root = psycho; + + psycho->upa_portid = portid; + + /* Map in PSYCHO register set and report the presence of this PSYCHO. */ + err = prom_getproperty(node, "reg", + (char *)&pr_regs[0], sizeof(pr_regs)); + if(err == 0 || err == -1) { + prom_printf("PSYCHO: Error, cannot get U2P registers " + "from PROM.\n"); + prom_halt(); + } + + /* Third REG in property is base of entire PSYCHO register space. */ + psycho->psycho_regs = sparc_alloc_io((pr_regs[2].phys_addr & 0xffffffff), + NULL, sizeof(struct psycho_regs), + "PSYCHO Registers", + (pr_regs[2].phys_addr >> 32), 0); + if(psycho->psycho_regs == NULL) { + prom_printf("PSYCHO: Error, cannot map PSYCHO " + "main registers.\n"); + prom_halt(); + } + + prom_printf("PSYCHO: Found controller, main regs at %p\n", + psycho->psycho_regs); + printk("PSYCHO: Found controller, main regs at %p\n", + psycho->psycho_regs); + + /* Now map in PCI config space for entire PSYCHO. */ + psycho->pci_config_space = + sparc_alloc_io(((pr_regs[2].phys_addr & 0xffffffff)+0x01000000), + NULL, 0x01000000, + "PCI Config Space", + (pr_regs[2].phys_addr >> 32), 0); + if(psycho->pci_config_space == NULL) { + prom_printf("PSYCHO: Error, cannot map PCI config space.\n"); + prom_halt(); + } + + /* Finally map in I/O space for both PBM's. This is essentially + * backwards compatability for non-conformant PCI cards which + * do not map themselves into the PCI memory space. + */ + psycho->pbm_B.pbm_IO = __va(pr_regs[2].phys_addr + 0x02000000UL); + psycho->pbm_A.pbm_IO = __va(pr_regs[2].phys_addr + 0x02010000UL); + + /* Now record MEM space for both PBM's. + * + * XXX Eddie, these can be reversed if BOOT_BUS pin is clear, is + * XXX there some way to find out what value of BOOT_BUS pin is? + */ + psycho->pbm_B.pbm_mem = __va(pr_regs[2].phys_addr + 0x180000000UL); + psycho->pbm_A.pbm_mem = __va(pr_regs[2].phys_addr + 0x100000000UL); + + /* Report some more info. */ + prom_printf("PSYCHO: PCI config space at %p\n", + psycho->pci_config_space); + prom_printf("PSYCHO: PBM A I/O space at %p, PBM B I/O at %p\n", + psycho->pbm_A.pbm_IO, psycho->pbm_B.pbm_IO); + prom_printf("PSYCHO: PBM A MEM at %p, PBM B MEM at %p\n"); + + printk("PSYCHO: PCI config space at %p\n", psycho->pci_config_space); + printk("PSYCHO: PBM A I/O space at %p, PBM B I/O at %p\n", + psycho->pbm_A.pbm_IO, psycho->pbm_B.pbm_IO); + + is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + + other_pbm: + if(is_pbm_a) + pbm = &psycho->pbm_A; + else + pbm = &psycho->pbm_B; + + pbm->parent = psycho; + pbm->prom_node = node; + + prom_getstring(node, "name", namebuf, sizeof(namebuf)); + strcpy(pbm->prom_name, namebuf); + + /* Now the ranges. */ + prom_pbm_ranges_init(node, pbm); + + /* Finally grab the pci bus root array for this pbm after + * having found the bus range existing under it. + */ + err = prom_getproperty(node, "bus-range", + (char *)&busrange[0], sizeof(busrange)); + if(err == 0 || err == -1) { + prom_printf("PSYCHO: Error, cannot get PCI bus range.\n"); + prom_halt(); + } + pbm->pci_first_busno = busrange[0]; + pbm->pci_last_busno = busrange[1]; + memset(&pbm->pci_bus, 0, sizeof(struct pci_bus)); + + node = prom_getsibling(node); + 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(); + } + + return memory_start; +} + +int pcibios_present(void) +{ + return psycho_root != NULL; +} + +int pcibios_find_device (unsigned short vendor, unsigned short device_id, + unsigned short index, unsigned char *bus, + unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->vendor == vendor && dev->device == device_id) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +int pcibios_find_class (unsigned int class_code, unsigned short index, + unsigned char *bus, unsigned char *devfn) +{ + unsigned int curr = 0; + struct pci_dev *dev; + + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->class == class_code) { + if (curr == index) { + *devfn = dev->devfn; + *bus = dev->bus->number; + return PCIBIOS_SUCCESSFUL; + } + ++curr; + } + } + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static void pbm_probe(struct linux_pbm_info *pbm, unsigned long *mstart) +{ + struct pci_bus *pbus = &pbm->pci_bus; + + /* PSYCHO PBM's include child PCI bridges in bus-range property, + * but we don't scan each of those ourselves, Linux generic PCI + * probing code will find child bridges and link them into this + * pbm's root PCI device hierarchy. + */ + pbus->number = pbm->pci_first_busno; + pbus->sysdata = pbm; + pbus->subordinate = pci_scan_bus(pbus, mstart); +} + +static void fill_in_pbm_cookies(struct linux_pbm_info *pbm) +{ + struct pci_bus *pbtmp, *pbus = &pbm->pci_bus; + struct pci_dev *pdev; + + for(pbtmp = pbus->children; pbtmp; pbtmp = pbtmp->children) + pbtmp->sysdata = pbm; + + for( ; pbus; pbus = pbus->children) + for(pdev = pbus->devices; pdev; pdev = pdev->sibling) + pdev->sysdata = pbm; +} + +static void fixup_pci_dev(struct pci_dev *pdev, + struct pci_bus *pbus, + struct linux_pbm_info *pbm) +{ + struct linux_prom_pci_registers pregs[PROMREG_MAX]; + int node; +#if 0 + int nregs, busno = pbus->number; +#endif + + node = prom_getchild(pbm->prom_node); + while(node) { + u32 devfn; + int err, nregs; + + err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs)); + if(err == 0 || err == -1) { + prom_printf("fixup_pci_dev: No PCI device reg property?!?!\n"); + prom_halt(); + } + nregs = (err / sizeof(struct linux_prom_pci_registers)); + + devfn = (pregs[0].phys_hi >> 8) & 0xff; + if(devfn == pdev->devfn) { + + return; + } + + node = prom_getsibling(node); + } + + prom_printf("fixup_pci_dev: Cannot find prom node for PCI device\n"); + prom_halt(); +} + +static void fixup_pci_bus(struct pci_bus *pbus, struct linux_pbm_info *pbm) +{ + struct pci_dev *pdev; + + for(pdev = pbus->devices; pdev; pdev = pdev->sibling) + fixup_pci_dev(pdev, pbus, pbm); + + for(pbus = pbus->children; pbus; pbus = pbus->children) + fixup_pci_bus(pbus, pbm); +} + +static void fixup_addr_irq(struct linux_pbm_info *pbm) +{ + struct pci_bus *pbus = &pbm->pci_bus; + + /* Work through top level devices (not bridges, those and their + * devices are handled specially in the next loop). + */ + fixup_pci_bus(pbus, pbm); +} + +/* Walk all PCI devices probes, fixing up base registers and IRQ registers. + * We use OBP for most of this work. + */ +static void psycho_final_fixup(struct linux_psycho *psycho) +{ + /* First, walk all PCI devices found. For each device, and + * PCI bridge which is not one of the PSYCHO PBM's, fill in the + * sysdata with a pointer to the PBM. + */ + fill_in_pbm_cookies(&psycho->pbm_A); + fill_in_pbm_cookies(&psycho->pbm_B); + + /* Second, fixup base address registers and IRQ lines... */ + fixup_addr_irq(&psycho->pbm_A); + fixup_addr_irq(&psycho->pbm_B); +} + +unsigned long pcibios_fixup(unsigned long memory_start, unsigned long memory_end) +{ + struct linux_psycho *psycho = psycho_root; + + pci_probe_enable = 1; + + /* XXX Really this should be per-PSYCHO, but the config space + * XXX reads and writes give us no way to know which PSYCHO + * XXX in which the config space reads should occur. + * XXX + * XXX Further thought says that we cannot change this generic + * XXX interface, else we'd break xfree86 and other parts of the + * XXX kernel (but whats more important is breaking userland for + * XXX the ix86/Alpha/etc. people). So we should define our own + * XXX internal extension initially, we can compile our own user + * XXX apps that need to get at PCI configuration space. + */ + + /* Probe busses under PBM A. */ + pbm_probe(&psycho->pbm_A, &memory_start); + + /* Probe busses under PBM B. */ + pbm_probe(&psycho->pbm_B, &memory_start); + + + psycho_final_fixup(psycho); + + return ebus_init(memory_start, memory_end); +} + +/* "PCI: The emerging standard..." 8-( */ +volatile int pci_poke_in_progress = 0; +volatile int pci_poke_faulted = 0; + +/* XXX Current PCI support code is broken, it assumes one master PCI config + * XXX space exists, on Ultra we can have many of them, especially with + * XXX 'dual-pci' boards on Sunfire/Starfire/Wildfire. + */ +static char *pci_mkaddr(unsigned char bus, unsigned char device_fn, + unsigned char where) +{ + unsigned long ret = (unsigned long) psycho_root->pci_config_space; + + ret |= (1 << 24); + ret |= ((bus & 0xff) << 16); + ret |= ((device_fn & 0xff) << 8); + ret |= (where & 0xfc); + return (unsigned char *)ret; +} + +static inline int out_of_range(unsigned char bus, unsigned char device_fn) +{ + return ((bus == 0 && PCI_SLOT(device_fn) > 4) || + (bus == 1 && PCI_SLOT(device_fn) > 6) || + (pci_probe_enable == 0)); +} + +int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned char *value) +{ + unsigned char *addr = pci_mkaddr(bus, device_fn, where); + unsigned int word, trapped; + + *value = 0xff; + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + trapped = pci_poke_faulted; + pci_poke_faulted = 0; + if(!trapped) { + switch(where & 3) { + case 0: + *value = word & 0xff; + break; + case 1: + *value = (word >> 8) & 0xff; + break; + case 2: + *value = (word >> 16) & 0xff; + break; + case 3: + *value = (word >> 24) & 0xff; + break; + }; + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned short *value) +{ + unsigned short *addr = (unsigned short *)pci_mkaddr(bus, device_fn, where); + unsigned int word, trapped; + + *value = 0xffff; + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + trapped = pci_poke_faulted; + pci_poke_faulted = 0; + if(!trapped) { + switch(where & 3) { + case 0: + *value = word & 0xffff; + break; + case 2: + *value = (word >> 16) & 0xffff; + break; + default: + prom_printf("pcibios_read_config_word: misaligned " + "reg [%x]\n", where); + prom_halt(); + }; + } + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned int *value) +{ + unsigned int *addr = (unsigned int *)pci_mkaddr(bus, device_fn, where); + unsigned int word, trapped; + + *value = 0xffffffff; + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + pci_poke_faulted = 0; + __asm__ __volatile__("membar #Sync\n\t" + "lduwa [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (word) + : "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + trapped = pci_poke_faulted; + pci_poke_faulted = 0; + if(!trapped) + *value = word; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned char value) +{ + unsigned char *addr = pci_mkaddr(bus, device_fn, where); + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + + /* Endianness doesn't matter but we have to get the memory + * barriers in there so... + */ + __asm__ __volatile__("membar #Sync\n\t" + "stba %0, [%1] %2\n\t" + "membar #Sync\n\t" + : /* no outputs */ + : "r" (value), "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned short value) +{ + unsigned short *addr = (unsigned short *)pci_mkaddr(bus, device_fn, where); + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + __asm__ __volatile__("membar #Sync\n\t" + "stha %0, [%1] %2\n\t" + "membar #Sync\n\t" + : /* no outputs */ + : "r" (value), "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + return PCIBIOS_SUCCESSFUL; +} + +int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, + unsigned char where, unsigned int value) +{ + unsigned int *addr = (unsigned int *)pci_mkaddr(bus, device_fn, where); + + if(out_of_range(bus, device_fn)) + return PCIBIOS_SUCCESSFUL; + + /* XXX Check no-probe-list conflicts here. XXX */ + + pci_poke_in_progress = 1; + __asm__ __volatile__("membar #Sync\n\t" + "stwa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (value), "r" (addr), "i" (ASI_PL)); + pci_poke_in_progress = 0; + return PCIBIOS_SUCCESSFUL; +} + +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; + + lock_kernel(); + switch(len) { + case 1: + pcibios_read_config_byte(bus, dfn, off, &ubyte); + put_user(ubyte, buf); + break; + case 2: + pcibios_read_config_word(bus, dfn, off, &ushort); + put_user(ushort, buf); + break; + case 4: + pcibios_read_config_dword(bus, dfn, off, &uint); + put_user(uint, 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; + + 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; +} + +#endif diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c --- v2.1.50/linux/arch/sparc64/kernel/ptrace.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/ptrace.c Sat Aug 16 09:51:09 1997 @@ -609,10 +609,6 @@ unsigned long tmp; int res; -#if 0 - /* XXX Find out what is really going on. */ - flush_cache_all(); -#endif /* Non-word alignment _not_ allowed on Sparc. */ if (current->tss.flags & SPARC_FLAG_32BIT) { unsigned int x; @@ -1055,7 +1051,7 @@ current->exit_code = SIGTRAP; current->state = TASK_STOPPED; current->tss.flags ^= MAGIC_CONSTANT; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); /* * this isn't the same as continuing with a signal, but it will do @@ -1067,9 +1063,9 @@ current->pid, current->exit_code); #endif if (current->exit_code) { - /* spin_lock_irq(¤t->sigmask_lock); */ + spin_lock_irq(¤t->sigmask_lock); current->signal |= (1 << (current->exit_code - 1)); - /* spin_unlock_irq(¤t->sigmask_lock); */ + spin_unlock_irq(¤t->sigmask_lock); } current->exit_code = 0; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.1.50/linux/arch/sparc64/kernel/rtrap.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/rtrap.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.28 1997/06/30 10:31:39 jj Exp $ +/* $Id: rtrap.S,v 1.30 1997/08/10 04:49:33 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -21,58 +21,60 @@ sethi %hi(bh_mask), %l1 ldx [%l2 + %lo(bh_active)], %l4 ldx [%l1 + %lo(bh_mask)], %l7 - andcc %l4, %l7, %g0 be,pt %xcc, 2f + nop call do_bottom_half nop 2: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 sethi %hi(0xf << 20), %l4 andcc %l1, TSTATE_PRIV, %l3 - and %l1, %l4, %l4 rdpr %pstate, %l7 + andn %l1, %l4, %l1 be,pt %icc, to_user andn %l7, PSTATE_IE, %l7 rt_continue: ld [%sp + PTREGS_OFF + PT_V9_FPRS], %l2 ld [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 - brnz,pn %l2, rt_fpu_restore ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2 + rt_after_fpu: ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 mov %g6, %l6 ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 - wrpr %l7, PSTATE_AG, %pstate ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 + ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ldx [%sp + PTREGS_OFF + PT_V9_I6], %i6 - ldx [%sp + PTREGS_OFF + PT_V9_I7], %i7 ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 + ldx [%sp + PTREGS_OFF + PT_V9_TPC], %l2 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %o2 wr %o3, %g0, %y srl %l4, 20, %l4 wrpr %l4, 0x0, %pil wrpr %g0, 0x1, %tl - wrpr %l1, %g0, %tstate wrpr %l2, %g0, %tpc - mov PRIMARY_CONTEXT, %l7 + + wr %g0, ASI_DMMU, %asi brnz,pn %l3, kern_rtt wrpr %o2, %g0, %tnpc - stxa %l0, [%l7] ASI_DMMU + stxa %l0, [%g0 + SECONDARY_CONTEXT] %asi + flush %l6 + stxa %l0, [%g0 + PRIMARY_CONTEXT] %asi flush %l6 rdpr %wstate, %l1 @@ -88,47 +90,54 @@ retry kern_rtt: restore retry -to_user: sethi %hi(need_resched), %l0 - ld [%l0 + %lo(need_resched)], %l0 +to_user: lduw [%g6 + AOFF_task_processor], %o0 + mov 1, %o1 + sethi %hi(need_resched), %l0 + ldx [%l0 + %lo(need_resched)], %l0 + sllx %o1, %o0, %o1 + wrpr %l7, PSTATE_IE, %pstate - brz,pt %l0, check_signal + andcc %o1, %l0, %g0 + be,pt %xcc, check_signal ldx [%g6 + AOFF_task_signal], %l0 - call schedule nop ldx [%g6 + AOFF_task_signal], %l0 nop + check_signal: ldx [%g6 + AOFF_task_blocked], %o0 andncc %l0, %o0, %g0 be,pt %xcc, check_user_wins ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 - mov %l5, %o2 mov %l6, %o3 call do_signal add %sp, STACK_BIAS + REGWIN_SZ, %o1 + ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 clr %l6 -check_user_wins: - brz,pt %o2, rt_continue +check_user_wins:brz,pt %o2, rt_continue nop - call fault_in_user_windows add %sp, STACK_BIAS + REGWIN_SZ, %o0 ba,a,pt %xcc, rt_continue rt_fpu_restore: wr %g0, FPRS_FEF, %fprs + add %sp, PTREGS_OFF + TRACEREG_SZ, %g4 wr %g0, ASI_BLK_P, %asi - membar #StoreLoad | #LoadLoad ldda [%g4 + 0x000] %asi, %f0 ldda [%g4 + 0x040] %asi, %f16 ldda [%g4 + 0x080] %asi, %f32 ldda [%g4 + 0x0c0] %asi, %f48 ldx [%g4 + 0x100], %fsr + ldx [%g4 + 0x108], %g3 membar #Sync - b,pt %xcc, rt_after_fpu wr %g3, 0, %gsr + nop + nop + nop + nop #undef PTREGS_OFF diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.1.50/linux/arch/sparc64/kernel/signal.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/signal.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.20 1997/07/14 03:10:28 davem Exp $ +/* $Id: signal.c,v 1.22 1997/08/05 19:19:36 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -54,12 +54,12 @@ if(tp->w_saved || (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || (!__access_ok((unsigned long)ucp, sizeof(*ucp)))) - do_exit(SIGSEGV); + 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) - do_exit(SIGSEGV); + goto do_sigsegv; if(regs->u_regs[UREG_I1]) { __get_user(current->blocked, &ucp->uc_sigmask); current->blocked &= _BLOCKABLE; @@ -100,6 +100,10 @@ __get_user(fpregs[33], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); regs->fprs = FPRS_FEF; } + return; +do_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } asmlinkage void sparc64_get_context(struct pt_regs *regs) @@ -113,7 +117,7 @@ synchronize_user_stack(); if(tp->w_saved || clear_user(ucp, sizeof(*ucp))) - do_exit(SIGSEGV); + goto do_sigsegv; mcp = &ucp->uc_mcontext; grp = &mcp->mc_gregs; @@ -156,6 +160,10 @@ __put_user(fpregs[33], &(mcp->mc_fpregs.mcfpu_gsr)); __put_user(FPRS_FEF, &(mcp->mc_fpregs.mcfpu_fprs)); } + return; +do_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } /* @@ -452,7 +460,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -498,7 +506,7 @@ current->exit_code = signr; if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.1.50/linux/arch/sparc64/kernel/signal32.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/signal32.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.26 1997/07/14 03:10:31 davem Exp $ +/* $Id: signal32.c,v 1.28 1997/08/05 19:19:40 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -555,6 +555,7 @@ synchronize_user_stack(); if (current->tss.w_saved){ printk ("Uh oh, w_saved is not zero (%ld)\n", current->tss.w_saved); + lock_kernel(); do_exit (SIGSEGV); } if(clear_user(uc, sizeof (*uc))) @@ -718,7 +719,7 @@ if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); if (!(signr = current->exit_code)) continue; @@ -764,7 +765,7 @@ current->exit_code = signr; if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & SA_NOCLDSTOP)) - notify_parent(current); + notify_parent(current, SIGCHLD); schedule(); continue; diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.1.50/linux/arch/sparc64/kernel/smp.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/smp.c Sat Aug 16 09:51:09 1997 @@ -10,11 +10,12 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -33,9 +34,9 @@ unsigned long cpu_present_map = 0; int smp_num_cpus = 1; int smp_threads_ready = 0; -volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; -struct cpuinfo_sparc cpu_data[NR_CPUS]; +struct cpuinfo_sparc cpu_data[NR_CPUS] __attribute__ ((aligned (64))); + static unsigned char boot_cpu_id = 0; static int smp_activated = 0; @@ -44,8 +45,6 @@ struct klock_info klock_info = { KLOCK_CLEAR, 0 }; -static volatile int smp_commenced = 0; - void smp_setup(char *str, int *ints) { /* XXX implement me XXX */ @@ -68,45 +67,64 @@ void smp_store_cpu_info(int id) { - cpu_data[id].udelay_val = loops_per_sec; + cpu_data[id].udelay_val = loops_per_sec; + cpu_data[id].irq_count = 0; + cpu_data[id].last_tlbversion_seen = tlb_context_cache & CTX_VERSION_MASK; + cpu_data[id].pgcache_size = 0; + cpu_data[id].pgd_cache = NULL; + cpu_data[id].pmd_cache = NULL; + cpu_data[id].pte_cache = NULL; } +extern void distribute_irqs(void); + void smp_commence(void) { - flush_cache_all(); - flush_tlb_all(); - smp_commenced = 1; - flush_cache_all(); - flush_tlb_all(); + distribute_irqs(); } static void smp_setup_percpu_timer(void); static volatile unsigned long callin_flag = 0; +extern void inherit_locked_prom_mappings(int save_p); +extern void cpu_probe(void); + void smp_callin(void) { int cpuid = hard_smp_processor_id(); - flush_cache_all(); - flush_tlb_all(); + inherit_locked_prom_mappings(0); + + __flush_cache_all(); + __flush_tlb_all(); + + cpu_probe(); + + /* Master did this already, now is the time for us to do it. */ + __asm__ __volatile__(" + sethi %%hi(0x80000000), %%g1 + sllx %%g1, 32, %%g1 + rd %%tick, %%g2 + add %%g2, 6, %%g2 + andn %%g2, %%g1, %%g2 + wrpr %%g2, 0, %%tick +" : /* no outputs */ + : /* no inputs */ + : "g1", "g2"); smp_setup_percpu_timer(); + __sti(); + calibrate_delay(); smp_store_cpu_info(cpuid); callin_flag = 1; __asm__ __volatile__("membar #Sync\n\t" "flush %%g6" : : : "memory"); - while(!task[cpuid]) - barrier(); - current = task[cpuid]; - - while(!smp_commenced) - barrier(); - - __sti(); + while(!smp_processors_ready) + membar("#LoadLoad"); } extern int cpu_idle(void *unused); @@ -130,18 +148,22 @@ panic("SMP bolixed\n"); } +static void smp_tickoffset_init(void); + extern struct prom_cpuinfo linux_cpus[NR_CPUS]; -extern unsigned long sparc64_cpu_startup; + +extern unsigned long smp_trampoline; void smp_boot_cpus(void) { int cpucount = 0, i; printk("Entering UltraSMPenguin Mode...\n"); + smp_tickoffset_init(); __sti(); cpu_present_map = 0; for(i = 0; i < linux_num_cpus; i++) - cpu_present_map |= (1 << i); + cpu_present_map |= (1UL << i); for(i = 0; i < NR_CPUS; i++) { cpu_number_map[i] = -1; cpu_logical_map[i] = -1; @@ -160,23 +182,24 @@ if(i == boot_cpu_id) continue; - if(cpu_present_map & (1 << i)) { + if(cpu_present_map & (1UL << i)) { + unsigned long entry = (unsigned long)(&smp_trampoline); struct task_struct *p; int timeout; + entry -= KERNBASE; kernel_thread(start_secondary, NULL, CLONE_PID); p = task[++cpucount]; p->processor = i; + callin_flag = 0; prom_startcpu(linux_cpus[i].prom_node, - ((unsigned long)&sparc64_cpu_startup), - ((unsigned long)p)); + entry, ((unsigned long)p)); for(timeout = 0; timeout < 5000000; timeout++) { - if(cpu_callin_map[i]) + if(callin_flag) break; udelay(100); } - if(cpu_callin_map[i]) { - /* XXX fix this */ + if(callin_flag) { cpu_number_map[i] = i; cpu_logical_map[i] = i; } else { @@ -184,19 +207,19 @@ printk("Processor %d is stuck.\n", i); } } - if(!(cpu_callin_map[i])) { - cpu_present_map &= ~(1 << i); + if(!callin_flag) { + cpu_present_map &= ~(1UL << i); cpu_number_map[i] = -1; } } if(cpucount == 0) { printk("Error: only one processor found.\n"); - cpu_present_map = (1 << smp_processor_id()); + cpu_present_map = (1UL << smp_processor_id()); } else { unsigned long bogosum = 0; for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) + if(cpu_present_map & (1UL << i)) bogosum += cpu_data[i].udelay_val; } printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n", @@ -207,27 +230,39 @@ smp_num_cpus = cpucount + 1; } smp_processors_ready = 1; + membar("#StoreStore | #StoreLoad"); } -/* XXX deprecated interface... */ +/* We don't even need to do anything, the only generic message pass done + * anymore is to stop all cpus during a panic(). When the user drops to + * the PROM prompt, the firmware will send the other cpu's it's MONDO + * vector anyways, so doing anything special here is pointless. + * + * This whole thing should go away anyways... + */ void smp_message_pass(int target, int msg, unsigned long data, int wait) { - printk("smp_message_pass() called, this is bad, spinning.\n"); - __sti(); - while(1) - barrier(); } +/* #define XCALL_DEBUG */ + static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, int cpu) { - u64 result, target = (cpu_number_map[cpu] << 14) | 0x70; + u64 result, target = (((unsigned long)linux_cpus[cpu].mid) << 14) | 0x70; + int stuck; +#ifdef XCALL_DEBUG + printk("CPU[%d]: xcall(data[%016lx:%016lx:%016lx],tgt[%016lx])\n", + smp_processor_id(), data0, data1, data2, target); +#endif +again: __asm__ __volatile__(" wrpr %0, %1, %%pstate wr %%g0, %2, %%asi stxa %3, [0x40] %%asi stxa %4, [0x50] %%asi stxa %5, [0x60] %%asi + membar #Sync stxa %%g0, [%6] %%asi membar #Sync" : /* No outputs */ @@ -235,27 +270,46 @@ "r" (data0), "r" (data1), "r" (data2), "r" (target)); /* NOTE: PSTATE_IE is still clear. */ + stuck = 100000; do { __asm__ __volatile__("ldxa [%%g0] %1, %0" : "=r" (result) : "i" (ASI_INTR_DISPATCH_STAT)); + if(result == 0) { + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" + : : "r" (pstate)); + return; + } + stuck -= 1; + if(stuck == 0) + break; } while(result & 0x1); __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); - if(result & 0x2) - panic("Penguin NACK's master!"); + if(stuck == 0) { +#ifdef XCALL_DEBUG + printk("CPU[%d]: mondo stuckage result[%016lx]\n", + smp_processor_id(), result); +#endif + } else { +#ifdef XCALL_DEBUG + printk("CPU[%d]: Penguin %d NACK's master.\n", smp_processor_id(), cpu); +#endif + udelay(2); + goto again; + } } void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2) { if(smp_processors_ready) { - unsigned long mask = (cpu_present_map & ~(1<cpu_vm_mask = (1UL << smp_processor_id()); + if(current->tss.current_ds) { + u32 ctx = mm->context & 0x1fff; + + current->tss.ctx = ctx; + spitfire_set_secondary_context(ctx); + __asm__ __volatile__("flush %g6"); + } + spin_unlock(&scheduler_lock); +} + void smp_flush_tlb_mm(struct mm_struct *mm) { u32 ctx = mm->context & 0x1fff; - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); + + if(mm == current->mm && mm->count == 1) { + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + return smp_cross_call_avoidance(mm); + } + smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); + +local_flush_and_out: __flush_tlb_mm(ctx); } @@ -292,22 +375,98 @@ unsigned long end) { u32 ctx = mm->context & 0x1fff; - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); + + if(mm == current->mm && mm->count == 1) { + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + return smp_cross_call_avoidance(mm); + } + smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); + +local_flush_and_out: __flush_tlb_range(ctx, start, end); } -void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page) { - struct mm_struct *mm = vma->vm_mm; u32 ctx = mm->context & 0x1fff; - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); + if(mm == current->mm && mm->count == 1) { + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + return smp_cross_call_avoidance(mm); + } else if(mm != current->mm && mm->count == 1) { + /* Try to handle two special cases to avoid cross calls + * in common scenerios where we are swapping process + * pages out. + */ + if((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK) + return; /* It's dead, nothing to do. */ + if(mm->cpu_vm_mask == (1UL << smp_processor_id())) + goto local_flush_and_out; + } + smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); + +local_flush_and_out: __flush_tlb_page(ctx, page); } -static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; +/* CPU capture. */ +#define CAPTURE_DEBUG +extern unsigned long xcall_capture; + +static atomic_t smp_capture_depth = ATOMIC_INIT(0); +static atomic_t smp_capture_registry = ATOMIC_INIT(0); +static unsigned long penguins_are_doing_time = 0; + +void smp_capture(void) +{ + int result = atomic_add_return(1, &smp_capture_depth); + + membar("#StoreStore | #LoadStore"); + if(result == 1) { + int ncpus = smp_num_cpus; + +#ifdef CAPTURE_DEBUG + printk("CPU[%d]: Sending penguins to jail...", smp_processor_id()); +#endif + penguins_are_doing_time = 1; + membar("#StoreStore | #LoadStore"); + atomic_inc(&smp_capture_registry); + smp_cross_call(&xcall_capture, 0, 0, 0); + while(atomic_read(&smp_capture_registry) != ncpus) + membar("#LoadLoad"); +#ifdef CAPTURE_DEBUG + printk("done\n"); +#endif + } +} + +void smp_release(void) +{ + if(atomic_dec_and_test(&smp_capture_depth)) { +#ifdef CAPTURE_DEBUG + printk("CPU[%d]: Giving pardon to imprisoned penguins\n", + smp_processor_id()); +#endif + penguins_are_doing_time = 0; + membar("#StoreStore | #StoreLoad"); + atomic_dec(&smp_capture_registry); + } +} + +/* Imprisoned penguins run with %pil == 15, but PSTATE_IE set, so they + * can service tlb flush xcalls... + */ +void smp_penguin_jailcell(void) +{ + flushw_user(); + atomic_inc(&smp_capture_registry); + membar("#StoreLoad | #StoreStore"); + while(penguins_are_doing_time) + membar("#LoadLoad"); + atomic_dec(&smp_capture_registry); +} static inline void sparc64_do_profile(unsigned long pc) { @@ -317,59 +476,100 @@ pc -= (unsigned long) &_stext; pc >>= prof_shift; - spin_lock(&ticker_lock); - if(pc < prof_len) - prof_buffer[pc]++; - else - prof_buffer[prof_len - 1]++; - spin_unlock(&ticker_lock); + if(pc >= prof_len) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); } } -unsigned int prof_multiplier[NR_CPUS]; -unsigned int prof_counter[NR_CPUS]; +static unsigned long real_tick_offset, current_tick_offset; + +#define prof_multiplier(__cpu) cpu_data[(__cpu)].multiplier +#define prof_counter(__cpu) cpu_data[(__cpu)].counter extern void update_one_process(struct task_struct *p, unsigned long ticks, unsigned long user, unsigned long system); void smp_percpu_timer_interrupt(struct pt_regs *regs) { + unsigned long compare, tick; int cpu = smp_processor_id(); int user = user_mode(regs); - /* XXX clear_profile_irq(cpu); */ - if(!user) - sparc64_do_profile(regs->tpc); - if(!--prof_counter[cpu]) { - if(current->pid) { - update_one_process(current, 1, user, !user); - if(--current->counter < 0) { - current->counter = 0; - need_resched = 1; - } - - spin_lock(&ticker_lock); - if(user) { - if(current->priority < DEF_PRIORITY) - kstat.cpu_nice++; - else - kstat.cpu_user++; - } else { - kstat.cpu_system++; + clear_softint((1UL << 0)); + do { + if(!user) + sparc64_do_profile(regs->tpc); + if(!--prof_counter(cpu)) { + if(current->pid) { + unsigned int *inc_me; + + update_one_process(current, 1, user, !user); + if(--current->counter < 0) { + current->counter = 0; + resched_force(); + } + + if(user) { + if(current->priority < DEF_PRIORITY) + inc_me = &kstat.cpu_nice; + else + inc_me = &kstat.cpu_user; + } else { + inc_me = &kstat.cpu_system; + } + atomic_inc((atomic_t *)inc_me); } - spin_unlock(&ticker_lock); + prof_counter(cpu) = prof_multiplier(cpu); } - prof_counter[cpu] = prof_multiplier[cpu]; - } + __asm__ __volatile__("rd %%tick_cmpr, %0\n\t" + "add %0, %2, %0\n\t" + "wr %0, 0x0, %%tick_cmpr\n\t" + "rd %%tick, %1" + : "=&r" (compare), "=r" (tick) + : "r" (current_tick_offset)); + } while (tick >= compare); } static void smp_setup_percpu_timer(void) { - /* XXX implement me */ + int cpu = smp_processor_id(); + + prof_counter(cpu) = prof_multiplier(cpu) = 1; + + __asm__ __volatile__("rd %%tick, %%g1\n\t" + "add %%g1, %0, %%g1\n\t" + "wr %%g1, 0x0, %%tick_cmpr" + : /* no outputs */ + : "r" (current_tick_offset) + : "g1"); +} + +static void smp_tickoffset_init(void) +{ + int node; + + node = linux_cpus[0].prom_node; + real_tick_offset = prom_getint(node, "clock-frequency"); + real_tick_offset = real_tick_offset / HZ; + current_tick_offset = real_tick_offset; } int setup_profiling_timer(unsigned int multiplier) { - /* XXX implement me */ + unsigned long flags; + int i; + + if((!multiplier) || (real_tick_offset / multiplier) < 1000) + return -EINVAL; + + save_and_cli(flags); + for(i = 0; i < NR_CPUS; i++) { + if(cpu_present_map & (1UL << i)) + prof_multiplier(i) = multiplier; + } + current_tick_offset = (real_tick_offset / multiplier); + restore_flags(flags); + return 0; } diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.1.50/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.11 1997/07/14 23:58:20 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.17 1997/08/10 01:51:01 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -49,7 +49,8 @@ extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern int __strncmp(const char *, const char *, __kernel_size_t); -extern unsigned int __csum_partial_copy_sparc_generic (const char *, char *); +extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, + int len, unsigned int sum); extern char saved_command_line[]; extern void bcopy (const char *, char *, int); @@ -57,6 +58,10 @@ extern void dump_thread(struct pt_regs *, struct user *); +#ifdef __SMP__ +extern spinlock_t scheduler_lock; +#endif + /* One thing to note is that the way the symbols of the mul/div * support routines are named is a mess, they all start with * a '.' which makes it a bitch to export, here is the trick: @@ -70,7 +75,17 @@ /* used by various drivers */ #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); +EXPORT_SYMBOL_PRIVATE(global_cli); +EXPORT_SYMBOL_PRIVATE(global_sti); +EXPORT_SYMBOL_PRIVATE(global_restore_flags); +#else +EXPORT_SYMBOL(local_irq_count); #endif EXPORT_SYMBOL_PRIVATE(_lock_kernel); EXPORT_SYMBOL_PRIVATE(_unlock_kernel); @@ -81,12 +96,13 @@ EXPORT_SYMBOL(request_fast_irq); EXPORT_SYMBOL(sparc_alloc_io); EXPORT_SYMBOL(sparc_free_io); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(__sparc64_bh_counter); EXPORT_SYMBOL(sparc_ultra_unmapioaddr); EXPORT_SYMBOL(mmu_get_scsi_sgl); EXPORT_SYMBOL(mmu_get_scsi_one); EXPORT_SYMBOL(sparc_dvma_malloc); +EXPORT_SYMBOL(mmu_release_scsi_one); +EXPORT_SYMBOL(mmu_release_scsi_sgl); #if CONFIG_SBUS EXPORT_SYMBOL(SBus_chain); EXPORT_SYMBOL(dma_chain); @@ -150,7 +166,7 @@ EXPORT_SYMBOL(__strncmp); EXPORT_SYMBOL(__memmove); -EXPORT_SYMBOL(__csum_partial_copy_sparc_generic); +EXPORT_SYMBOL(csum_partial_copy_sparc64); /* Moving data to/from userspace. */ EXPORT_SYMBOL(__copy_to_user); diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.1.50/linux/arch/sparc64/kernel/sys_sparc.c Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/sys_sparc.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.2 1997/07/05 09:52:34 davem Exp $ +/* $Id: sys_sparc.c,v 1.3 1997/07/29 09:35:10 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -220,46 +220,36 @@ sparc_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction) { struct sigaction new_sa, *p; - int err = -EINVAL; - lock_kernel(); if(signum < 0) { current->tss.new_signal = 1; signum = -signum; } - if (signum<1 || signum>32) - goto out; + return -EINVAL; p = signum - 1 + current->sig->action; if (action) { - err = -EINVAL; if (signum==SIGKILL || signum==SIGSTOP) - goto out; - err = -EFAULT; + return -EINVAL; if(copy_from_user(&new_sa, action, sizeof(struct sigaction))) - goto out; + return -EFAULT; if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - err = verify_area(VERIFY_READ, new_sa.sa_handler, 1); + int err = verify_area(VERIFY_READ, new_sa.sa_handler, 1); if (err) - goto out; + return err; } } - if (oldaction) { - err = -EFAULT; if (copy_to_user(oldaction, p, sizeof(struct sigaction))) - goto out; + return -EFAULT; } - if (action) { + spin_lock_irq(¤t->sig->siglock); *p = new_sa; check_pending(signum); + spin_unlock_irq(¤t->sig->siglock); } - - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* only AP+ systems have sys_aplib */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.1.50/linux/arch/sparc64/kernel/sys_sparc32.c Sun Jul 27 12:11:00 1997 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sat Aug 16 10:00:20 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.44 1997/07/20 09:18:47 davem Exp $ +/* $Id: sys_sparc32.c,v 1.43 1997/07/17 02:20:45 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -87,10 +87,11 @@ void putname32(char * name) { - if (name_page_cache32 == 0) - name_page_cache32 = (unsigned long) name; - else - free_page((unsigned long) name); + unsigned long page; + + page = xchg(&name_page_cache32, ((unsigned long)name)); + if(page) + free_page(page); } int getname32(u32 filename, char **result) @@ -98,8 +99,7 @@ unsigned long page; int retval; - page = name_page_cache32; - name_page_cache32 = 0; + page = xchg(&name_page_cache32, NULL); if (!page) { page = __get_free_page(GFP_KERNEL); if (!page) @@ -1010,7 +1010,7 @@ lock_kernel (); p = (char *)__get_free_page (GFP_KERNEL); if (!p) - goto out; + goto out_nofree; q = (u32 *)p; Inp = (u32 *)A(inp); @@ -1079,6 +1079,7 @@ } out: free_page ((unsigned long)p); +out_nofree: unlock_kernel(); return ret; } @@ -2110,54 +2111,45 @@ { struct sigaction32 new_sa, old_sa; struct sigaction *p; - int err = -EINVAL; - lock_kernel(); if(signum < 0) { current->tss.new_signal = 1; signum = -signum; } - if (signum<1 || signum>32) - goto out; + return -EINVAL; p = signum - 1 + current->sig->action; if (action) { - err = -EINVAL; if (signum==SIGKILL || signum==SIGSTOP) - goto out; - err = -EFAULT; + return -EINVAL; if(copy_from_user(&new_sa, A(action), sizeof(struct sigaction32))) - goto out; + return -EFAULT; if (((__sighandler_t)A(new_sa.sa_handler)) != SIG_DFL && ((__sighandler_t)A(new_sa.sa_handler)) != SIG_IGN) { - err = verify_area(VERIFY_READ, (__sighandler_t)A(new_sa.sa_handler), 1); + int err = verify_area(VERIFY_READ, + (__sighandler_t)A(new_sa.sa_handler), 1); if (err) - goto out; + return err; } } - if (oldaction) { - err = -EFAULT; old_sa.sa_handler = (unsigned)(u64)(p->sa_handler); old_sa.sa_mask = (sigset_t32)(p->sa_mask); old_sa.sa_flags = (unsigned)(p->sa_flags); old_sa.sa_restorer = (unsigned)(u64)(p->sa_restorer); if (copy_to_user(A(oldaction), &old_sa, sizeof(struct sigaction32))) - goto out; + return -EFAULT; } - if (action) { + spin_lock_irq(¤t->sig->siglock); p->sa_handler = (__sighandler_t)A(new_sa.sa_handler); p->sa_mask = (sigset_t)(new_sa.sa_mask); p->sa_flags = new_sa.sa_flags; p->sa_restorer = (void (*)(void))A(new_sa.sa_restorer); check_pending(signum); + spin_unlock_irq(¤t->sig->siglock); } - - err = 0; -out: - unlock_kernel(); - return err; + return 0; } /* @@ -2298,7 +2290,7 @@ base = 1; lock_kernel(); - filename = getname((char *)(unsigned long)(u32)regs->u_regs[base + UREG_I0]); + filename = getname((char *)A((u32)regs->u_regs[base + UREG_I0])); error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; @@ -2720,9 +2712,7 @@ return 0; } -extern asmlinkage int sys_nfsservctl(int cmd, - struct nfsctl_arg *arg, - union nfsctl_res *resp); +extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp); int asmlinkage sys32_nfsservctl(int cmd, u32 u_argp, u32 u_resp) { diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.1.50/linux/arch/sparc64/kernel/systbls.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/systbls.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.21 1997/07/05 07:09:17 davem Exp $ +/* $Id: systbls.S,v 1.23 1997/08/09 18:33:17 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -10,213 +10,214 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ - .data - .align 8 + .text + .align 1024 /* First, the 32-bit Linux native syscall table. */ .globl sys_call_table32 sys_call_table32: -/*0*/ .xword sys_setup, sys_exit, sys_fork, sys32_read, sys32_write -/*5*/ .xword sys32_open, sys_close, sys32_wait4, sys32_creat, sys32_link -/*10*/ .xword sys32_unlink, sunos_execv, sys32_chdir, sys_nis_syscall, sys32_mknod -/*15*/ .xword sys32_chmod, sys32_chown, sparc32_brk, sys_nis_syscall, sys32_lseek -/*20*/ .xword sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid -/*25*/ .xword sys32_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause -/*30*/ .xword sys32_utime, sys_stty, sys_gtty, sys32_access, sys_nice - .xword sys_ftime, sys_sync, sys_kill, sys32_newstat, sys_nis_syscall -/*40*/ .xword sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_profil - .xword sys_nis_syscall, sys_setgid, sys_getgid, sys32_signal, sys_geteuid -/*50*/ .xword sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl - .xword sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve -/*60*/ .xword sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize - .xword sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*70*/ .xword sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect - .xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups -/*80*/ .xword sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall - .xword sys32_swapon, sys32_getitimer, sys_nis_syscall, sys32_sethostname, sys_nis_syscall -/*90*/ .xword sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall - .xword sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*100*/ .xword sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall -/*120*/ .xword sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod - .xword sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate -/*130*/ .xword sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall -/*140*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit - .xword sys32_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*150*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys32_umount -/*160*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_setdomainname, sys_nis_syscall - .xword sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall -/*170*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents - .xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module - .xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname -/*190*/ .xword sys32_init_module, sys32_personality, sys_prof, sys_break, sys_lock - .xword sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask -/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir - .xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall -/*210*/ .xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo - .xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex -/*220*/ .xword sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid - .xword sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid -/*230*/ .xword sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall - .xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall -/*240*/ .xword sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep -/*250*/ .xword sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl - .xword sys_aplib, sys_nis_syscall +/*0*/ .word sys_setup, sys_exit, sys_fork, sys32_read, sys32_write +/*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys32_link +/*10*/ .word sys32_unlink, sunos_execv, sys32_chdir, sys_nis_syscall, sys32_mknod +/*15*/ .word sys32_chmod, sys32_chown, sparc32_brk, sys_nis_syscall, sys32_lseek +/*20*/ .word sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid +/*25*/ .word sys32_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause +/*30*/ .word sys32_utime, sys_stty, sys_gtty, sys32_access, sys_nice + .word sys_ftime, sys_sync, sys_kill, sys32_newstat, sys_nis_syscall +/*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_profil + .word sys_nis_syscall, sys_setgid, sys_getgid, sys32_signal, sys_geteuid +/*50*/ .word sys_getegid, sys32_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl + .word sys32_reboot, sys_nis_syscall, sys32_symlink, sys32_readlink, sys32_execve +/*60*/ .word sys_umask, sys32_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize + .word sys32_msync, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*70*/ .word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys32_munmap, sys32_mprotect + .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups +/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall + .word sys32_swapon, sys32_getitimer, sys_nis_syscall, sys32_sethostname, sys_nis_syscall +/*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall + .word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*100*/ .word sys_getpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall +/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod + .word sys_nis_syscall, sys32_setreuid, sys_setregid, sys32_rename, sys32_truncate +/*130*/ .word sys32_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys32_mkdir, sys32_rmdir, sys_nis_syscall, sys_nis_syscall +/*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit + .word sys32_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys32_umount +/*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_setdomainname, sys_nis_syscall + .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall +/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents + .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module + .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname +/*190*/ .word sys32_init_module, sys32_personality, sys_prof, sys_break, sys_lock + .word sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask +/*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir + .word sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall +/*210*/ .word sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo + .word sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex +/*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid + .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid +/*230*/ .word sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall + .word sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall +/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep +/*250*/ .word sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl + .word sys_aplib /* Now the 64-bit native Linux syscall table. */ + .align 1024 .globl sys_call_table64, sys_call_table sys_call_table64: sys_call_table: -/*0*/ .xword sys_setup, sys_exit, sys_fork, sys_read, sys_write -/*5*/ .xword sys_open, sys_close, sys_wait4, sys_creat, sys_link -/*10*/ .xword sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys_mknod -/*15*/ .xword sys_chmod, sys_chown, sparc_brk, sys_nis_syscall, sys_lseek -/*20*/ .xword sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid -/*25*/ .xword sys_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause -/*30*/ .xword sys_utime, sys_stty, sys_gtty, sys_access, sys_nice - .xword sys_ftime, sys_sync, sys_kill, sys_newstat, sys_nis_syscall -/*40*/ .xword sys_newlstat, sys_dup, sys_pipe, sys_times, sys_profil - .xword sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid -/*50*/ .xword sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl - .xword sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve -/*60*/ .xword sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize - .xword sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*70*/ .xword sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect - .xword sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups -/*80*/ .xword sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall - .xword sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall -/*90*/ .xword sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall - .xword sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept -/*100*/ .xword sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind - .xword sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*110*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg - .xword sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall -/*120*/ .xword sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod - .xword sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate -/*130*/ .xword sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown - .xword sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall -/*140*/ .xword sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit - .xword sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*150*/ .xword sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount -/*160*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall - .xword sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall -/*170*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents - .xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module - .xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname -/*190*/ .xword sys_init_module, sys_personality, sys_prof, sys_break, sys_lock - .xword sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask -/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall - .xword sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall -/*210*/ .xword sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo - .xword sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex -/*220*/ .xword sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid - .xword sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid -/*230*/ .xword sys_llseek, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall - .xword sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall -/*240*/ .xword sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep -/*250*/ .xword sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl - .xword sys_aplib, sys_nis_syscall +/*0*/ .word sys_setup, sys_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 +/*15*/ .word sys_chmod, sys_chown, sparc_brk, sys_nis_syscall, sys_lseek +/*20*/ .word sys_getpid, sys_nis_syscall, sys_nis_syscall, sys_setuid, sys_getuid +/*25*/ .word sys_time, sys_ptrace, sys_alarm, sys_nis_syscall, sys_pause +/*30*/ .word sys_utime, sys_stty, sys_gtty, sys_access, sys_nice + .word sys_ftime, sys_sync, sys_kill, sys_newstat, sys_nis_syscall +/*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_profil + .word sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid +/*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl + .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve +/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize + .word sys_nis_syscall, sys_vfork, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect + .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups +/*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall + .word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall +/*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall + .word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept +/*100*/ .word sys_getpriority, sys_send, sys_recv, sys_nis_syscall, sys_bind + .word sys_setsockopt, sys_listen, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg + .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall +/*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod + .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate +/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown + .word sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall +/*140*/ .word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit + .word sys_setrlimit, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount +/*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_setdomainname, sys_nis_syscall + .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall +/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents + .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module + .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname +/*190*/ .word sys_init_module, sys_personality, sys_prof, sys_break, sys_lock + .word sys_mpx, sys_ulimit, sys_getppid, sparc_sigaction, sys_sgetmask +/*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall + .word sys_nis_syscall, sys_nis_syscall, sys_syslog, sys_nis_syscall, sys_nis_syscall +/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo + .word sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex +/*220*/ .word sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid + .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid +/*230*/ .word sys_llseek, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall + .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall +/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep +/*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl + .word sys_aplib /* Now the 32-bit SunOS syscall table. */ - .align 8 + .align 1024 .globl sunos_sys_table sunos_sys_table: -/*0*/ .xword sunos_indir, sys_exit, sys_fork - .xword sunos_read, sunos_write, sunos_open - .xword sys_close, sunos_wait4, sys32_creat - .xword sys32_link, sys32_unlink, sunos_execv - .xword sys32_chdir, sunos_nosys, sys32_mknod - .xword sys32_chmod, sys32_chown, sunos_brk - .xword sunos_nosys, sys32_lseek, sunos_getpid - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_getuid, sunos_nosys, sys_ptrace - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sys32_access, sunos_nosys, sunos_nosys - .xword sys_sync, sys_kill, sys32_newstat - .xword sunos_nosys, sys32_newlstat, sys_dup - .xword sys_pipe, sunos_nosys, sys_profil - .xword sunos_nosys, sunos_nosys, sunos_getgid - .xword sunos_nosys, sunos_nosys -/*50*/ .xword sunos_nosys, sys32_acct, sunos_nosys - .xword sunos_mctl, sunos_ioctl, sys32_reboot - .xword sunos_nosys, sys32_symlink, sys32_readlink - .xword sys32_execve, sys_umask, sys32_chroot - .xword sys32_newfstat, sunos_nosys, sys_getpagesize - .xword sys32_msync, sys_vfork, sunos_nosys - .xword sunos_nosys, sunos_sbrk, sunos_sstk - .xword sunos_mmap, sunos_vadvise, sys32_munmap - .xword sys32_mprotect, sunos_madvise, sys_vhangup - .xword sunos_nosys, sunos_mincore, sys32_getgroups - .xword sys32_setgroups, sys_getpgrp, sunos_setpgrp - .xword sys32_setitimer, sunos_nosys, sys32_swapon - .xword sys32_getitimer, sys32_gethostname, sys32_sethostname - .xword sunos_getdtablesize, sys_dup2, sunos_nop - .xword sys32_fcntl, sunos_select, sunos_nop - .xword sys_fsync, sys_setpriority, sys_socket - .xword sys32_connect, sunos_accept -/*100*/ .xword sys_getpriority, sunos_send, sunos_recv - .xword sunos_nosys, sys32_bind, sunos_setsockopt - .xword sys_listen, sunos_nosys, sunos_sigaction - .xword sunos_sigblock, sunos_sigsetmask, sys_sigpause - .xword sys32_sigstack, sys32_recvmsg, sys32_sendmsg - .xword sunos_nosys, sys_gettimeofday, sys32_getrusage - .xword sunos_getsockopt, sunos_nosys, sunos_readv - .xword sunos_writev, sys_settimeofday, sys_fchown - .xword sys_fchmod, sys32_recvfrom, sys32_setreuid - .xword sys_setregid, sys32_rename, sys32_truncate - .xword sys32_ftruncate, sys_flock, sunos_nosys - .xword sys32_sendto, sys_shutdown, sys_socketpair - .xword sys32_mkdir, sys32_rmdir, sys32_utimes - .xword sys_sigreturn, sunos_nosys, sys32_getpeername - .xword sunos_gethostid, sunos_nosys, sys32_getrlimit - .xword sys32_setrlimit, sunos_killpg, sunos_nosys - .xword sunos_nosys, sunos_nosys -/*150*/ .xword sys32_getsockname, sunos_nosys, sunos_nosys - .xword sys32_poll, sunos_nosys, sunos_nosys - .xword sunos_getdirentries, sys32_statfs, sys32_fstatfs - .xword sys32_umount, sunos_nosys, sunos_nosys - .xword sunos_getdomainname, sys32_setdomainname - .xword sunos_nosys, sys32_quotactl, sunos_nosys - .xword sunos_mount, sys32_ustat, sunos_semsys - .xword sunos_nosys, sunos_shmsys, sunos_audit - .xword sunos_nosys, sunos_getdents, sys_setsid - .xword sys_fchdir, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sys32_sigpending, sunos_nosys - .xword sys_setpgid, sunos_pathconf, sunos_fpathconf - .xword sunos_sysconf, sunos_uname, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys -/*200*/ .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys -/*250*/ .xword sunos_nosys, sunos_nosys, sunos_nosys - .xword sunos_nosys, sunos_nosys, sys_aplib +/*0*/ .word sunos_indir, sys_exit, sys_fork + .word sunos_read, sunos_write, sunos_open + .word sys_close, sunos_wait4, sys32_creat + .word sys32_link, sys32_unlink, sunos_execv + .word sys32_chdir, sunos_nosys, sys32_mknod + .word sys32_chmod, sys32_chown, sunos_brk + .word sunos_nosys, sys32_lseek, sunos_getpid + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_getuid, sunos_nosys, sys_ptrace + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sys32_access, sunos_nosys, sunos_nosys + .word sys_sync, sys_kill, sys32_newstat + .word sunos_nosys, sys32_newlstat, sys_dup + .word sys_pipe, sunos_nosys, sys_profil + .word sunos_nosys, sunos_nosys, sunos_getgid + .word sunos_nosys, sunos_nosys +/*50*/ .word sunos_nosys, sys32_acct, sunos_nosys + .word sunos_mctl, sunos_ioctl, sys32_reboot + .word sunos_nosys, sys32_symlink, sys32_readlink + .word sys32_execve, sys_umask, sys32_chroot + .word sys32_newfstat, sunos_nosys, sys_getpagesize + .word sys32_msync, sys_vfork, sunos_nosys + .word sunos_nosys, sunos_sbrk, sunos_sstk + .word sunos_mmap, sunos_vadvise, sys32_munmap + .word sys32_mprotect, sunos_madvise, sys_vhangup + .word sunos_nosys, sunos_mincore, sys32_getgroups + .word sys32_setgroups, sys_getpgrp, sunos_setpgrp + .word sys32_setitimer, sunos_nosys, sys32_swapon + .word sys32_getitimer, sys32_gethostname, sys32_sethostname + .word sunos_getdtablesize, sys_dup2, sunos_nop + .word sys32_fcntl, sunos_select, sunos_nop + .word sys_fsync, sys_setpriority, sys_socket + .word sys32_connect, sunos_accept +/*100*/ .word sys_getpriority, sunos_send, sunos_recv + .word sunos_nosys, sys32_bind, sunos_setsockopt + .word sys_listen, sunos_nosys, sunos_sigaction + .word sunos_sigblock, sunos_sigsetmask, sys_sigpause + .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg + .word sunos_nosys, sys_gettimeofday, sys32_getrusage + .word sunos_getsockopt, sunos_nosys, sunos_readv + .word sunos_writev, sys_settimeofday, sys_fchown + .word sys_fchmod, sys32_recvfrom, sys32_setreuid + .word sys_setregid, sys32_rename, sys32_truncate + .word sys32_ftruncate, sys_flock, sunos_nosys + .word sys32_sendto, sys_shutdown, sys_socketpair + .word sys32_mkdir, sys32_rmdir, sys32_utimes + .word sys_sigreturn, sunos_nosys, sys32_getpeername + .word sunos_gethostid, sunos_nosys, sys32_getrlimit + .word sys32_setrlimit, sunos_killpg, sunos_nosys + .word sunos_nosys, sunos_nosys +/*150*/ .word sys32_getsockname, sunos_nosys, sunos_nosys + .word sys32_poll, sunos_nosys, sunos_nosys + .word sunos_getdirentries, sys32_statfs, sys32_fstatfs + .word sys32_umount, sunos_nosys, sunos_nosys + .word sunos_getdomainname, sys32_setdomainname + .word sunos_nosys, sys32_quotactl, sunos_nosys + .word sunos_mount, sys32_ustat, sunos_semsys + .word sunos_nosys, sunos_shmsys, sunos_audit + .word sunos_nosys, sunos_getdents, sys_setsid + .word sys_fchdir, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sys32_sigpending, sunos_nosys + .word sys_setpgid, sunos_pathconf, sunos_fpathconf + .word sunos_sysconf, sunos_uname, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys +/*200*/ .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys +/*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys, sunos_nosys, sys_aplib diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- v2.1.50/linux/arch/sparc64/kernel/time.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/time.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.5 1997/07/23 11:32:06 davem Exp $ +/* $Id: time.c,v 1.9 1997/08/12 04:12:40 ecd Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -8,6 +8,7 @@ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) */ +#include #include #include #include @@ -23,6 +24,10 @@ #include #include #include +#include +#include +#include +#include struct mostek48t02 *mstk48t02_regs = 0; struct mostek48t08 *mstk48t08_regs = 0; @@ -155,33 +160,55 @@ /* Probe for the real time clock chip. */ -__initfunc(static void clock_probe(void)) +__initfunc(static void set_system_time(void)) { - struct linux_prom_registers clk_reg[2]; - char model[128]; - int node, sbusnd, err; + unsigned int year, mon, day, hour, min, sec; + struct mostek48t02 *mregs; - /* XXX HACK HACK HACK, delete me soon */ - struct linux_prom_ranges XXX_sbus_ranges[PROMREG_MAX]; - int XXX_sbus_nranges; - - node = prom_getchild(prom_root_node); - sbusnd = prom_searchsiblings(node, "sbus"); - node = prom_getchild(sbusnd); + do_get_fast_time = do_gettimeofday; - if(node == 0 || node == -1) { - prom_printf("clock_probe: Serious problem can't find sbus PROM node.\n"); + mregs = mstk48t02_regs; + if(!mregs) { + prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); + } + + mregs->creg |= MSTK_CREG_READ; + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + mregs->creg &= ~MSTK_CREG_READ; +} + +__initfunc(void clock_probe(void)) +{ + struct linux_prom_registers clk_reg[2]; + char model[128]; + int node, busnd = -1, err; + + if(central_bus != NULL) { + busnd = central_bus->child->prom_node; + } +#ifdef CONFIG_PCI + else if (ebus_chain != NULL) { + busnd = ebus_chain->prom_node; + } +#endif + else { + busnd = SBus_chain->prom_node; } - /* XXX FIX ME */ - err = prom_getproperty(sbusnd, "ranges", (char *) XXX_sbus_ranges, - sizeof(XXX_sbus_ranges)); - if(err == -1) { - prom_printf("clock_probe: Cannot get XXX sbus ranges\n"); + if(busnd == -1) { + prom_printf("clock_probe: problem, cannot find bus to search.\n"); prom_halt(); } - XXX_sbus_nranges = (err / sizeof(struct linux_prom_ranges)); + + node = prom_getchild(busnd); while(1) { prom_getstring(node, "model", model, sizeof(model)); @@ -199,12 +226,34 @@ err = prom_getproperty(node, "reg", (char *)clk_reg, sizeof(clk_reg)); if(err == -1) { - prom_printf("clock_probe: Cannot make Mostek\n"); + prom_printf("clock_probe: Cannot get Mostek reg property\n"); prom_halt(); } - /* XXX fix me badly */ - prom_adjust_regs(clk_reg, 1, XXX_sbus_ranges, XXX_sbus_nranges); + if(central_bus) { + prom_apply_fhc_ranges(central_bus->child, clk_reg, 1); + prom_apply_central_ranges(central_bus, clk_reg, 1); + } +#ifdef CONFIG_PCI + else if (ebus_chain) { + struct linux_ebus_device *edev; + + for_each_ebusdev(edev, ebus_chain) + if (edev->prom_node == node) + break; + if (!edev) { + prom_printf("%s: Mostek not probed by EBUS\n"); + prom_halt(); + } + + clk_reg[0] = edev->regs[0]; + } +#endif + else { + prom_adjust_regs(clk_reg, 1, + SBus_chain->sbus_ranges, + SBus_chain->num_sbus_ranges); + } if(model[5] == '0' && model[6] == '2') { mstk48t02_regs = (struct mostek48t02 *) @@ -234,6 +283,8 @@ /* Kick start the clock if it is completely stopped. */ if (mstk48t02_regs->sec & MSTK_STOP) kick_start_clock(); + + set_system_time(); } #ifndef BCD_TO_BIN @@ -246,29 +297,10 @@ __initfunc(void time_init(void)) { - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - - do_get_fast_time = do_gettimeofday; - - clock_probe(); - - mregs = mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; - mregs->creg &= ~MSTK_CREG_READ; + /* 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 *)); @@ -307,8 +339,11 @@ sethi %hi(xtime), %g2 ldx [%o1 + %lo(linux_timers)], %g3 1: ldd [%g2 + %lo(xtime)], %o4 + membar #LoadLoad | #MemIssue ldx [%g3], %o1 + membar #LoadLoad | #MemIssue ldd [%g2 + %lo(xtime)], %o2 + membar #LoadLoad xor %o4, %o2, %o2 xor %o5, %o3, %o3 orcc %o2, %o3, %g0 diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S --- v2.1.50/linux/arch/sparc64/kernel/trampoline.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/kernel/trampoline.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.1 1997/07/24 14:47:53 davem Exp $ +/* $Id: trampoline.S,v 1.2 1997/07/28 02:57:32 davem Exp $ * trampoline.S: Jump start slave processors on sparc64. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,16 +13,28 @@ #include #include + .data + .align 8 + .globl smp_trampoline +smp_trampoline: .skip 0x300 + .text - .globl sparc64_cpu_startup + .align 8 + .globl sparc64_cpu_startup, sparc64_cpu_startup_end sparc64_cpu_startup: flushw mov (LSU_CONTROL_IC | LSU_CONTROL_DC | LSU_CONTROL_IM | LSU_CONTROL_DM), %g1 stxa %g1, [%g0] ASI_LSU_CONTROL + membar #Sync wrpr %g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate wrpr %g0, 15, %pil - mov %o0, %g6 + sethi %uhi(PAGE_OFFSET), %g4 + sllx %g4, 32, %g4 + + /* XXX Buggy PROM... */ + srl %o0, 0, %g6 + add %g6, %g4, %g6 sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 sllx %g5, 32, %g5 @@ -33,9 +45,8 @@ sllx %g3, 32, %g3 sethi %hi(_PAGE_PADDR), %g7 or %g7, %lo(_PAGE_PADDR), %g7 - or %g3, %g7, %g7 + or %g3, %g7, %g3 - /* Find TLB entry we are executing out of. */ clr %l0 set 0x1fff, %l2 rd %pc, %l3 @@ -69,7 +80,7 @@ andn %g1, %l2, %g1 cmp %g1, %g3 blu,pn %xcc, 2f - cmp %g1, %g7 + cmp %g1, %g7 bgeu,pn %xcc, 2f nop stxa %g0, [%l7] ASI_IMMU @@ -109,7 +120,7 @@ stxa %g3, [%l7] ASI_IMMU stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS membar #Sync - flush %g6 + flush %g3 membar #Sync b,pt %xcc, 1f nop @@ -125,9 +136,6 @@ stxa %g0, [%g7] ASI_DMMU membar #Sync - sethi %uhi(PAGE_OFFSET), %g4 - sllx %g4, 32, %g4 - mov TLB_TAG_ACCESS, %g2 stxa %g3, [%g2] ASI_IMMU stxa %g3, [%g2] ASI_DMMU @@ -143,7 +151,7 @@ stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS membar #Sync - flush %g6 + flush %g3 membar #Sync mov 1, %g5 @@ -184,7 +192,6 @@ stxa %o5, [%o4] ASI_IMMU membar #Sync - wrpr %g0, 0, %pil or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate @@ -195,3 +202,6 @@ call cpu_panic nop 1: b,a,pt %xcc, 1b + + .align 8 +sparc64_cpu_startup_end: diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.1.50/linux/arch/sparc64/kernel/traps.c Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/traps.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.29 1997/07/05 09:52:38 davem Exp $ +/* $Id: traps.c,v 1.31 1997/08/11 14:35:33 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -25,6 +25,7 @@ #include #include #include +#include /* #define SYSCALL_TRACING */ /* #define VERBOSE_SYSCALL_TRACING */ @@ -194,8 +195,55 @@ send_sig(SIGSEGV, current, 1); } +#ifdef CONFIG_PCI +/* This is really pathetic... */ +/* #define DEBUG_PCI_POKES */ +extern volatile int pci_poke_in_progress; +extern volatile int pci_poke_faulted; +#endif + void do_dae(struct pt_regs *regs) { +#ifdef CONFIG_PCI +#ifdef DEBUG_PCI_POKES + prom_printf(" (POKE "); +#endif + if(pci_poke_in_progress) { + unsigned long va; +#ifdef DEBUG_PCI_POKES + prom_printf("tpc[%016lx] tnpc[%016lx] ", + regs->tpc, regs->tnpc); +#endif + pci_poke_faulted = 1; + regs->tnpc = regs->tpc + 4; + + +#ifdef DEBUG_PCI_POKES + prom_printf("PCI) "); + /* prom_halt(); */ +#endif + /* Re-enable I/D caches, Ultra turned them off. */ + for(va = 0; va < (PAGE_SIZE << 1); va += 32) { + spitfire_put_icache_tag(va, 0x0); + spitfire_put_dcache_tag(va, 0x0); + } + __asm__ __volatile__("flush %%g6\n\t" + "membar #Sync\n\t" + "stxa %0, [%%g0] %1\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC | + LSU_CONTROL_IM | LSU_CONTROL_DM), + "i" (ASI_LSU_CONTROL) + : "memory"); + return; + } +#ifdef DEBUG_PCI_POKES + prom_printf("USER) "); + prom_printf("tpc[%016lx] tnpc[%016lx]\n"); + prom_halt(); +#endif +#endif send_sig(SIGSEGV, current, 1); } @@ -215,11 +263,9 @@ regs->tpc = regs->tnpc; regs->tnpc += 4; } else { - lock_kernel(); current->tss.sig_address = regs->tpc; current->tss.sig_desc = SUBSIG_FPERROR; send_sig(SIGFPE, current, 1); - unlock_kernel(); } } @@ -288,6 +334,7 @@ } printk("Instruction DUMP:"); instruction_dump ((unsigned int *) regs->tpc); + lock_kernel(); /* Or else! */ if(regs->tstate & TSTATE_PRIV) do_exit(SIGKILL); do_exit(SIGSEGV); @@ -298,13 +345,11 @@ unsigned long pc = regs->tpc; unsigned long tstate = regs->tstate; - lock_kernel(); if(tstate & TSTATE_PRIV) die_if_kernel("Kernel illegal instruction", regs); current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_ILLINST; send_sig(SIGILL, current, 1); - unlock_kernel(); } void mem_address_unaligned(struct pt_regs *regs) @@ -333,19 +378,16 @@ current->tss.sig_address = regs->tpc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); - unlock_kernel(); } void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long tstate) { - lock_kernel(); if(tstate & TSTATE_PRIV) die_if_kernel("Penguin instruction from Penguin mode??!?!", regs); current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); - unlock_kernel(); } /* XXX User may want to be allowed to do this. XXX */ @@ -353,7 +395,6 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long tstate) { - lock_kernel(); if(regs->tstate & TSTATE_PRIV) { printk("KERNEL MNA at pc %016lx npc %016lx called by %016lx\n", pc, npc, regs->u_regs[UREG_RETPC]); @@ -363,15 +404,12 @@ current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_PRIVINST; send_sig(SIGBUS, current, 1); - unlock_kernel(); } void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr) { - lock_kernel(); send_sig(SIGILL, current, 1); - unlock_kernel(); } /* Trap level 1 stuff or other traps we should never see... */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- v2.1.50/linux/arch/sparc64/kernel/ttable.S Mon Jul 7 08:18:54 1997 +++ linux/arch/sparc64/kernel/ttable.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.18 1997/07/05 09:52:41 davem Exp $ +/* $Id: ttable.S,v 1.19 1997/07/26 18:38:56 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -44,7 +44,8 @@ tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) -tl0_irq13: TRAP_IRQ(handler_irq, 13) TRAP_IRQ(handler_irq, 14) +tl0_irq13: TRAP_IRQ(handler_irq, 13) +tl0_itick: TRAP_TICK tl0_irq15: TRAP_IRQ(handler_irq, 15) tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S --- v2.1.50/linux/arch/sparc64/kernel/winfixup.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/kernel/winfixup.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.16 1997/07/13 20:02:42 davem Exp $ +/* $Id: winfixup.S,v 1.19 1997/08/08 08:33:37 jj Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -143,8 +143,9 @@ retry window_scheisse_from_user_common: wrpr %g1, %cwp + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 window_scheisse_merge: srlx %l5, PAGE_SHIFT, %o1 @@ -244,8 +245,9 @@ retry window_mna_from_user_common: wrpr %g1, %cwp + sethi %hi(109f), %g7 ba,pt %xcc, etrap - rd %pc, %g7 +109: or %g7, %lo(109b), %g7 window_mna_merge: call mem_address_unaligned add %sp, STACK_BIAS + REGWIN_SZ, %o0 diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/Makefile linux/arch/sparc64/lib/Makefile --- v2.1.50/linux/arch/sparc64/lib/Makefile Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/Makefile Sat Aug 16 10:00:22 1997 @@ -6,7 +6,7 @@ OBJS = blockops.o locks.o strlen.o strncmp.o \ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ - VIScopy.o VISbzero.o VISmemset.o VIScsum.o + VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VISbzero.S linux/arch/sparc64/lib/VISbzero.S --- v2.1.50/linux/arch/sparc64/lib/VISbzero.S Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/lib/VISbzero.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: VISbzero.S,v 1.4 1997/06/28 17:21:21 jj Exp $ +/* $Id: VISbzero.S,v 1.6 1997/08/08 08:34:00 jj Exp $ * VISbzero.S: High speed clear operations utilizing the UltraSparc * Visual Instruction Set. * @@ -147,7 +147,7 @@ #else wr %g0, ASI_BLK_P, %asi #endif - membar #StoreStore | #LoadStore + membar #StoreLoad | #StoreStore | #LoadStore fzero %f0 andcc %o3, 0xc0, %o2 and %o1, 0x3f, %o1 @@ -181,15 +181,23 @@ wr %g0, 0, %fprs wr %g7, 0x0, %asi #endif - membar #Sync + membar #StoreLoad | #StoreStore 9: andcc %o1, 0xf8, %o2 be,pn %xcc, 13f andcc %o1, 7, %o1 +#ifdef __KERNEL__ +14: sethi %hi(13f), %o4 + srl %o2, 1, %o3 + sub %o4, %o3, %o4 + jmpl %o4 + %lo(13f), %g0 + add %o0, %o2, %o0 +#else 14: rd %pc, %o4 srl %o2, 1, %o3 sub %o4, %o3, %o4 jmpl %o4 + (13f - 14b), %g0 add %o0, %o2, %o0 +#endif 12: ZERO_BLOCKS(%o0, 0xc8, %g0) ZERO_BLOCKS(%o0, 0x88, %g0) ZERO_BLOCKS(%o0, 0x48, %g0) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S --- v2.1.50/linux/arch/sparc64/lib/VIScopy.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/VIScopy.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: VIScopy.S,v 1.9 1997/07/13 18:23:39 davem Exp $ +/* $Id: VIScopy.S,v 1.11 1997/08/08 08:34:02 jj Exp $ * VIScopy.S: High speed copy operations utilizing the UltraSparc * Visual Instruction Set. * @@ -303,7 +303,7 @@ sethi %hi(8192), %o2 ! IEU0 Group mov ASI_BLK_P, asi_src ! IEU1 b,pt %xcc, dest_is_64byte_aligned ! CTI - mov ASI_BLK_COMMIT_P, asi_dest ! IEU0 Group + mov ASI_BLK_P, asi_dest ! IEU0 Group .align 32 .globl __copy_from_user @@ -446,6 +446,13 @@ EXVIS1(LDBLK [%o1 + 0x40] ASIBLK, %f16) ! LSU Group sub %g7, 0x80, %g7 ! IEU0 EXVIS(LDBLK [%o1 + 0x80] ASIBLK, %f32) ! LSU Group +#ifdef __KERNEL__ +vispc: sll %g2, 9, %g2 ! IEU0 Group + sethi %hi(vis00), %g5 ! IEU1 + or %g5, %lo(vis00), %g5 ! IEU0 Group + jmpl %g5 + %g2, %g0 ! CTI Group brk forced + addcc %o1, 0xc0, %o1 ! IEU1 Group +#else ! Clk1 Group 8-( ! Clk2 Group 8-( ! Clk3 Group 8-( @@ -455,6 +462,7 @@ sll %g2, 9, %g2 ! IEU0 jmpl %g5 + %g2, %g0 ! CTI Group brk forced addcc %o1, 0xc0, %o1 ! IEU1 Group +#endif .align 512 /* OK, here comes the fun part... */ vis00:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g7, vis01) FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g7, vis02) @@ -721,20 +729,21 @@ 3: andcc %o2, 0x70, %g7 ! IEU1 Group 41: be,pn %xcc, 80f ! CTI andcc %o2, 8, %g0 ! IEU1 Group - ! Clk1 8-( - ! Clk2 8-( - ! Clk3 8-( - ! Clk4 8-( -79: rd %pc, %o5 ! PDU Group #ifdef __KERNEL__ +79: sethi %hi(80f), %o5 ! IEU0 sll %g7, 1, %g5 ! IEU0 Group add %o1, %g7, %o1 ! IEU1 srl %g7, 1, %g2 ! IEU0 Group sub %o5, %g5, %o5 ! IEU1 sub %o5, %g2, %o5 ! IEU0 Group - jmpl %o5 + %lo(80f - 79b), %g0 ! CTI Group brk forced + jmpl %o5 + %lo(80f), %g0 ! CTI Group brk forced add %o0, %g7, %o0 ! IEU0 Group #else + ! Clk1 8-( + ! Clk2 8-( + ! Clk3 8-( + ! Clk4 8-( +79: rd %pc, %o5 ! PDU Group sll %g7, 1, %g5 ! IEU0 Group add %o1, %g7, %o1 ! IEU1 sub %o5, %g5, %o5 ! IEU0 Group @@ -814,19 +823,20 @@ andcc %o2, 0x70, %g7 ! IEU1 be,pn %xcc, 84f ! CTI andcc %o2, 8, %g0 ! IEU1 Group +#ifdef __KERNEL__ +83: srl %g7, 1, %g5 ! IEU0 + sethi %hi(84f), %o5 ! IEU0 Group + add %g7, %g5, %g5 ! IEU1 + add %o1, %g7, %o1 ! IEU0 Group + sub %o5, %g5, %o5 ! IEU1 + jmpl %o5 + %lo(84f), %g0 ! CTI Group brk forced + add %o0, %g7, %o0 ! IEU0 Group +#else ! Clk1 8-( ! Clk2 8-( ! Clk3 8-( ! Clk4 8-( 83: rd %pc, %o5 ! PDU Group -#ifdef __KERNEL__ - srl %g7, 1, %g5 ! IEU0 Group - add %g7, %g5, %g5 ! IEU0 Group - add %o1, %g7, %o1 ! IEU1 - sub %o5, %g5, %o5 ! IEU0 Group - jmpl %o5 + %lo(84f - 83b), %g0 ! CTI Group brk forced - add %o0, %g7, %o0 ! IEU0 Group -#else add %o1, %g7, %o1 ! IEU0 Group sub %o5, %g7, %o5 ! IEU1 jmpl %o5 + %lo(84f - 83b), %g0 ! CTI Group brk forced diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VIScsum.S linux/arch/sparc64/lib/VIScsum.S --- v2.1.50/linux/arch/sparc64/lib/VIScsum.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/VIScsum.S Sat Aug 16 10:00:22 1997 @@ -434,3 +434,447 @@ add %o2, 1, %o2 /* IEU0 */ 1: ba,pt %xcc, 25b /* CTI Group */ sllx %o2, 32, %g1 /* IEU0 */ +/* $Id: VIScsum.S,v 1.2 1997/08/08 08:34:05 jj Exp $ + * VIScsum.S: High bandwidth IP checksumming utilizing the UltraSparc + * Visual Instruction Set. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * Based on older sparc32/sparc64 checksum.S, which is: + * + * Copyright(C) 1995 Linus Torvalds + * Copyright(C) 1995 Miguel de Icaza + * Copyright(C) 1996,1997 David S. Miller + * derived from: + * Linux/Alpha checksum c-code + * Linux/ix86 inline checksum assembly + * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code) + * David Mosberger-Tang for optimized reference c-code + * BSD4.4 portable checksum routine + */ + +#ifdef __sparc_v9__ +#define STACKOFF 2175 +#else +#define STACKOFF 64 +#endif + +#ifdef __KERNEL__ +#include +#include +#else +#define ASI_BLK_P 0xf0 +#define FRPS_FEF 0x04 +#endif + +/* Dobrou noc, SunSoft engineers. Spete sladce. + * This has a couple of tricks in and those + * tricks are UltraLinux trade secrets :)) + */ + +#define START_THE_TRICK(fz,f0,f2,f4,f6,f8,f10) \ + fcmpgt32 %fz, %f0, %g1 /* FPM Group */; \ + fcmpgt32 %fz, %f2, %g2 /* FPM Group */; \ + fcmpgt32 %fz, %f4, %g3 /* FPM Group */; \ + fcmpgt32 %fz, %f6, %g5 /* FPM Group */; \ + inc %g1 /* IEU0 */; \ + fcmpgt32 %fz, %f8, %g7 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + inc %g2 /* IEU1 */; \ + fcmpgt32 %fz, %f10, %o3 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + add %o2, %g1, %o2 /* IEU1 */; \ + add %g3, 1, %g3 /* IEU0 Group */; \ + srl %g3, 1, %g3 /* IEU0 Group */; \ + add %o2, %g2, %o2 /* IEU1 */; \ + inc %g5 /* IEU0 Group */; \ + add %o2, %g3, %o2 /* IEU1 */; + +#define DO_THE_TRICK(O12,O14,f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14) \ + fcmpgt32 %O12, %f12, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + fpadd32 %F0, %f0, %F0 /* FPA */; \ + fcmpgt32 %O14, %f14, %o5 /* FPM Group */; \ + srl %g7, 1, %g7 /* IEU0 */; \ + add %o2, %g5, %o2 /* IEU1 */; \ + fpadd32 %F2, %f2, %F2 /* FPA */; \ + inc %o3 /* IEU0 Group */; \ + add %o2, %g7, %o2 /* IEU1 */; \ + fcmpgt32 %f0, %F0, %g1 /* FPM Group */; \ + srl %o3, 1, %o3 /* IEU0 */; \ + inc %o4 /* IEU1 */; \ + fpadd32 %F4, %f4, %F4 /* FPA */; \ + fcmpgt32 %f2, %F2, %g2 /* FPM Group */; \ + srl %o4, 1, %o4 /* IEU0 */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + fpadd32 %F6, %f6, %F6 /* FPA */; \ + inc %o5 /* IEU0 Group */; \ + add %o2, %o4, %o2 /* IEU1 */; \ + fcmpgt32 %f4, %F4, %g3 /* FPM Group */; \ + srl %o5, 1, %o5 /* IEU0 */; \ + inc %g1 /* IEU1 */; \ + fpadd32 %F8, %f8, %F8 /* FPA */; \ + fcmpgt32 %f6, %F6, %g5 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + add %o2, %o5, %o2 /* IEU1 */; \ + fpadd32 %F10, %f10, %F10 /* FPA */; \ + inc %g2 /* IEU0 Group */; \ + add %o2, %g1, %o2 /* IEU1 */; \ + fcmpgt32 %f8, %F8, %g7 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + inc %g3 /* IEU1 */; \ + fpadd32 %F12, %f12, %F12 /* FPA */; \ + fcmpgt32 %f10, %F10, %o3 /* FPM Group */; \ + srl %g3, 1, %g3 /* IEU0 */; \ + add %o2, %g2, %o2 /* IEU1 */; \ + fpadd32 %F14, %f14, %F14 /* FPA */; \ + inc %g5 /* IEU0 Group */; \ + add %o2, %g3, %o2 /* IEU1 */; + +#define END_THE_TRICK(O12,O14,f0,f2,f4,f6,f8,f10,f12,f14,S0,S1,S2,S3,T0,T1,U0,fz) \ + fcmpgt32 %O12, %f12, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + fpadd32 %f2, %f0, %S0 /* FPA */; \ + fcmpgt32 %O14, %f14, %o5 /* FPM Group */; \ + srl %g7, 1, %g7 /* IEU0 */; \ + add %o2, %g5, %o2 /* IEU1 */; \ + fpadd32 %f6, %f4, %S1 /* FPA */; \ + inc %o3 /* IEU0 Group */; \ + add %o2, %g7, %o2 /* IEU1 */; \ + fcmpgt32 %f0, %S0, %g1 /* FPM Group */; \ + srl %o3, 1, %o3 /* IEU0 */; \ + inc %o4 /* IEU1 */; \ + fpadd32 %f10, %f8, %S2 /* FPA */; \ + fcmpgt32 %f4, %S1, %g2 /* FPM Group */; \ + srl %o4, 1, %o4 /* IEU0 */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + fpadd32 %f14, %f12, %S3 /* FPA */; \ + inc %o5 /* IEU0 Group */; \ + add %o2, %o4, %o2 /* IEU1 */; \ + fzero %fz /* FPA */; \ + fcmpgt32 %f8, %S2, %g3 /* FPM Group */; \ + srl %o5, 1, %o5 /* IEU0 */; \ + inc %g1 /* IEU1 */; \ + fpadd32 %S0, %S1, %T0 /* FPA */; \ + fcmpgt32 %f12, %S3, %g5 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + add %o2, %o5, %o2 /* IEU1 */; \ + fpadd32 %S2, %S3, %T1 /* FPA */; \ + inc %g2 /* IEU0 Group */; \ + add %o2, %g1, %o2 /* IEU1 */; \ + fcmpgt32 %S0, %T0, %g7 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + inc %g3 /* IEU1 */; \ + fcmpgt32 %S2, %T1, %o3 /* FPM Group */; \ + srl %g3, 1, %g3 /* IEU0 */; \ + add %o2, %g2, %o2 /* IEU1 */; \ + inc %g5 /* IEU0 Group */; \ + add %o2, %g3, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %f2, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + fpadd32 %T0, %T1, %U0 /* FPA */; \ + fcmpgt32 %fz, %f6, %o5 /* FPM Group */; \ + srl %g7, 1, %g7 /* IEU0 */; \ + add %o2, %g5, %o2 /* IEU1 */; \ + inc %o3 /* IEU0 Group */; \ + add %o2, %g7, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %f10, %g1 /* FPM Group */; \ + srl %o3, 1, %o3 /* IEU0 */; \ + inc %o4 /* IEU1 */; \ + fcmpgt32 %fz, %f14, %g2 /* FPM Group */; \ + srl %o4, 1, %o4 /* IEU0 */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + std %U0, [%sp + STACKOFF] /* Store Group */; \ + inc %o5 /* IEU0 */; \ + sub %o2, %o4, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %S1, %g3 /* FPM Group */; \ + srl %o5, 1, %o5 /* IEU0 */; \ + inc %g1 /* IEU1 */; \ + fcmpgt32 %fz, %S3, %g5 /* FPM Group */; \ + srl %g1, 1, %g1 /* IEU0 */; \ + sub %o2, %o5, %o2 /* IEU1 */; \ + ldx [%sp + STACKOFF], %o5 /* Load Group */; \ + inc %g2 /* IEU0 */; \ + sub %o2, %g1, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %T1, %g7 /* FPM Group */; \ + srl %g2, 1, %g2 /* IEU0 */; \ + inc %g3 /* IEU1 */; \ + fcmpgt32 %T0, %U0, %o3 /* FPM Group */; \ + srl %g3, 1, %g3 /* IEU0 */; \ + sub %o2, %g2, %o2 /* IEU1 */; \ + inc %g5 /* IEU0 Group */; \ + sub %o2, %g3, %o2 /* IEU1 */; \ + fcmpgt32 %fz, %U0, %o4 /* FPM Group */; \ + srl %g5, 1, %g5 /* IEU0 */; \ + inc %g7 /* IEU1 */; \ + srl %g7, 1, %g7 /* IEU0 Group */; \ + sub %o2, %g5, %o2 /* IEU1 */; \ + inc %o3 /* IEU0 Group */; \ + sub %o2, %g7, %o2 /* IEU1 */; \ + srl %o3, 1, %o3 /* IEU0 Group */; \ + inc %o4 /* IEU1 */; \ + srl %o4, 1, %o4 /* IEU0 Group */; \ + add %o2, %o3, %o2 /* IEU1 */; \ + sub %o2, %o4, %o2 /* IEU0 Group */; \ + addcc %o2, %o5, %o2 /* IEU1 Group */; \ + bcs,a,pn %xcc, 33f /* CTI */; \ + add %o2, 1, %o2 /* IEU0 */; \ +33: /* That's it */; + +#define CSUM_LASTCHUNK(offset) \ + ldx [%o0 - offset - 0x10], %g2; \ + ldx [%o0 - offset - 0x08], %g3; \ + addcc %g2, %o2, %o2; \ + bcs,a,pn %xcc, 31f; \ + add %o2, 1, %o2; \ +31: addcc %g3, %o2, %o2; \ + bcs,a,pn %xcc, 32f; \ + add %o2, 1, %o2; \ +32: + + .text + .globl csum_partial + .align 32 +csum_partial: + andcc %o0, 7, %g0 /* IEU1 Group */ + be,pt %icc, 4f /* CTI */ + andcc %o0, 0x38, %g3 /* IEU1 */ + mov 1, %g5 /* IEU0 Group */ + cmp %o1, 6 /* IEU1 */ + bl,pn %icc, 21f /* CTI */ + andcc %o0, 2, %g0 /* IEU1 Group */ + be,pt %icc, 1f /* CTI */ + and %o0, 4, %g7 /* IEU0 */ + lduh [%o0], %g2 /* Load */ + sub %o1, 2, %o1 /* IEU0 Group */ + add %o0, 2, %o0 /* IEU1 */ + andcc %o0, 4, %g7 /* IEU1 Group */ + sll %g5, 16, %g5 /* IEU0 */ + sll %g2, 16, %g2 /* IEU0 Group */ + addcc %g2, %o2, %o2 /* IEU1 Group (regdep) */ + bcs,a,pn %icc, 1f /* CTI */ + add %o2, %g5, %o2 /* IEU0 */ +1: ld [%o0], %g2 /* Load */ + brz,a,pn %g7, 4f /* CTI+IEU1 Group */ + and %o0, 0x38, %g3 /* IEU0 */ + add %o0, 4, %o0 /* IEU0 Group */ + sub %o1, 4, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %icc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: and %o0, 0x38, %g3 /* IEU1 Group */ +4: srl %o2, 0, %o2 /* IEU0 Group */ + mov 0x40, %g1 /* IEU1 */ + brz,pn %g3, 3f /* CTI+IEU1 Group */ + sub %g1, %g3, %g1 /* IEU0 */ + cmp %o1, 56 /* IEU1 Group */ + blu,pn %icc, 20f /* CTI */ + andcc %o0, 8, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + ldx [%o0], %g2 /* Load */ + add %o0, 8, %o0 /* IEU0 Group */ + sub %o1, 8, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: andcc %g1, 0x10, %g0 /* IEU1 Group */ + be,pn %icc, 2f /* CTI */ + and %g1, 0x20, %g1 /* IEU0 */ + ldx [%o0], %g2 /* Load */ + ldx [%o0+8], %g3 /* Load Group */ + add %o0, 16, %o0 /* IEU0 */ + sub %o1, 16, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g3, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 2f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +2: brz,pn %g1, 3f /* CTI+IEU1 Group */ + ldx [%o0], %g2 /* Load */ + ldx [%o0+8], %g3 /* Load Group */ + ldx [%o0+16], %g5 /* Load Group */ + ldx [%o0+24], %g7 /* Load Group */ + add %o0, 32, %o0 /* IEU0 */ + sub %o1, 32, %o1 /* IEU1 */ + addcc %g2, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g3, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g5, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: addcc %g7, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 3f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +3: cmp %o1, 0xc0 /* IEU1 Group */ + blu,pn %icc, 20f /* CTI */ + sllx %o2, 32, %g1 /* IEU0 */ + addcc %o2, %g1, %o2 /* IEU1 Group */ + sub %o1, 0xc0, %o1 /* IEU0 */ + wr %g0, ASI_BLK_P, %asi /* LSU Group */ +#ifdef __KERNEL__ + wr %g0, FPRS_FEF, %fprs /* LSU Group */ +#endif + membar #StoreLoad /* LSU Group */ + srlx %o2, 32, %o2 /* IEU0 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU1 */ +1: andcc %o1, 0x80, %g0 /* IEU1 Group */ + bne,pn %icc, 7f /* CTI */ + andcc %o1, 0x40, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + fzero %f12 /* FPA */ + fzero %f14 /* FPA Group */ + ldda [%o0 + 0x000] %asi, %f16 + ldda [%o0 + 0x040] %asi, %f32 + ldda [%o0 + 0x080] %asi, %f48 + START_THE_TRICK(f12,f16,f18,f20,f22,f24,f26) + ba,a,pt %xcc, 3f +6: sub %o0, 0x40, %o0 /* IEU0 Group */ + fzero %f28 /* FPA */ + fzero %f30 /* FPA Group */ + ldda [%o0 + 0x040] %asi, %f32 + ldda [%o0 + 0x080] %asi, %f48 + ldda [%o0 + 0x0c0] %asi, %f0 + START_THE_TRICK(f28,f32,f34,f36,f38,f40,f42) + ba,a,pt %xcc, 4f +7: bne,pt %icc, 8f /* CTI */ + fzero %f44 /* FPA */ + add %o0, 0x40, %o0 /* IEU0 Group */ + fzero %f60 /* FPA */ + fzero %f62 /* FPA Group */ + ldda [%o0 - 0x040] %asi, %f0 + ldda [%o0 + 0x000] %asi, %f16 + ldda [%o0 + 0x040] %asi, %f32 + START_THE_TRICK(f60,f0,f2,f4,f6,f8,f10) + ba,a,pt %xcc, 2f +8: add %o0, 0x80, %o0 /* IEU0 Group */ + fzero %f46 /* FPA */ + ldda [%o0 - 0x080] %asi, %f48 + ldda [%o0 - 0x040] %asi, %f0 + ldda [%o0 + 0x000] %asi, %f16 + START_THE_TRICK(f44,f48,f50,f52,f54,f56,f58) +1: DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14) + ldda [%o0 + 0x040] %asi, %f32 +2: DO_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30) + ldda [%o0 + 0x080] %asi, %f48 +3: DO_THE_TRICK(f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46) + ldda [%o0 + 0x0c0] %asi, %f0 +4: DO_THE_TRICK(f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,f48,f50,f52,f54,f56,f58,f60,f62) + add %o0, 0x100, %o0 /* IEU0 Group */ + subcc %o1, 0x100, %o1 /* IEU1 */ + bgeu,a,pt %icc, 1b /* CTI */ + ldda [%o0 + 0x000] %asi, %f16 + membar #Sync /* LSU Group */ + DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14) + END_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30) + and %o1, 0x3f, %o1 /* IEU0 Group */ +#ifdef __KERNEL__ + wr %g0, 0, %fprs /* LSU Group */ +#endif +20: andcc %o1, 0xf0, %g1 /* IEU1 Group */ + be,pn %icc, 23f /* CTI */ + and %o1, 0xf, %o3 /* IEU0 */ +#ifdef __KERNEL__ +22: sll %g1, 1, %o4 /* IEU0 Group */ + sethi %hi(23f), %g7 /* IEU1 */ + sub %g7, %o4, %g7 /* IEU0 Group */ + jmpl %g7 + %lo(23f), %g0 /* CTI Group brk forced */ + add %o0, %g1, %o0 /* IEU0 */ +#else +22: rd %pc, %g7 /* LSU Group+4bubbles */ + sll %g1, 1, %o4 /* IEU0 Group */ + sub %g7, %o4, %g7 /* IEU0 Group (regdep) */ + jmpl %g7 + (23f - 22b), %g0 /* CTI Group brk forced */ + add %o0, %g1, %o0 /* IEU0 */ +#endif + CSUM_LASTCHUNK(0xe0) + CSUM_LASTCHUNK(0xd0) + CSUM_LASTCHUNK(0xc0) + CSUM_LASTCHUNK(0xb0) + CSUM_LASTCHUNK(0xa0) + CSUM_LASTCHUNK(0x90) + CSUM_LASTCHUNK(0x80) + CSUM_LASTCHUNK(0x70) + CSUM_LASTCHUNK(0x60) + CSUM_LASTCHUNK(0x50) + CSUM_LASTCHUNK(0x40) + CSUM_LASTCHUNK(0x30) + CSUM_LASTCHUNK(0x20) + CSUM_LASTCHUNK(0x10) + CSUM_LASTCHUNK(0x00) +23: brnz,pn %o3, 26f /* CTI+IEU1 Group */ +24: sllx %o2, 32, %g1 /* IEU0 */ +25: addcc %o2, %g1, %o0 /* IEU1 Group */ + srlx %o0, 32, %o0 /* IEU0 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o0, 1, %o0 /* IEU1 */ +1: retl /* CTI Group brk forced */ + srl %o0, 0, %o0 /* IEU0 */ +26: andcc %o1, 8, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + ldx [%o0], %g3 /* Load */ + add %o0, 8, %o0 /* IEU0 Group */ + addcc %g3, %o2, %o2 /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: andcc %o1, 4, %g0 /* IEU1 Group */ + be,a,pn %icc, 1f /* CTI */ + clr %g2 /* IEU0 */ + ld [%o0], %g2 /* Load */ + add %o0, 4, %o0 /* IEU0 Group */ + sllx %g2, 32, %g2 /* IEU0 Group */ +1: andcc %o1, 2, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o4 /* IEU0 Group */ + lduh [%o0], %o4 /* Load */ + add %o0, 2, %o0 /* IEU1 */ + sll %o4, 16, %o4 /* IEU0 Group */ +1: andcc %o1, 1, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o5 /* IEU0 Group */ + ldub [%o0], %o5 /* Load */ + sll %o5, 8, %o5 /* IEU0 Group */ +1: or %g2, %o4, %o4 /* IEU1 */ + or %o5, %o4, %o4 /* IEU0 Group (regdep) */ + addcc %o4, %o2, %o2 /* IEU1 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: ba,pt %xcc, 25b /* CTI Group */ + sllx %o2, 32, %g1 /* IEU0 */ +21: srl %o2, 0, %o2 /* IEU0 Group */ + cmp %o1, 0 /* IEU1 */ + be,pn %icc, 24b /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + be,a,pn %icc, 1f /* CTI */ + clr %g2 /* IEU0 */ + lduh [%o0], %g3 /* Load */ + lduh [%o0+2], %g2 /* Load Group */ + add %o0, 4, %o0 /* IEU0 Group */ + sllx %g3, 48, %g3 /* IEU0 Group */ + sllx %g2, 32, %g2 /* IEU0 Group */ + or %g3, %g2, %g2 /* IEU0 Group */ +1: andcc %o1, 2, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o4 /* IEU0 Group */ + lduh [%o0], %o4 /* Load */ + add %o0, 2, %o0 /* IEU1 */ + sll %o4, 16, %o4 /* IEU0 Group */ +1: andcc %o1, 1, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o5 /* IEU0 Group */ + ldub [%o0], %o5 /* Load */ + sll %o5, 8, %o5 /* IEU0 Group */ +1: or %g2, %o4, %o4 /* IEU1 */ + or %o5, %o4, %o4 /* IEU0 Group (regdep) */ + addcc %o4, %o2, %o2 /* IEU1 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %o2, 1, %o2 /* IEU0 */ +1: ba,pt %xcc, 25b /* CTI Group */ + sllx %o2, 32, %g1 /* IEU0 */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VIScsumcopy.S linux/arch/sparc64/lib/VIScsumcopy.S --- v2.1.50/linux/arch/sparc64/lib/VIScsumcopy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/VIScsumcopy.S Sat Aug 16 09:51:09 1997 @@ -0,0 +1,880 @@ +/* $Id: VIScsumcopy.S,v 1.1 1997/08/09 18:14:29 jj Exp $ + * VIScsumcopy.S: High bandwidth IP checksumming with simultaneous + * copying utilizing the UltraSparc Visual Instruction Set. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * Based on older sparc32/sparc64 checksum.S, which is: + * + * Copyright(C) 1995 Linus Torvalds + * Copyright(C) 1995 Miguel de Icaza + * Copyright(C) 1996,1997 David S. Miller + * derived from: + * Linux/Alpha checksum c-code + * Linux/ix86 inline checksum assembly + * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code) + * David Mosberger-Tang for optimized reference c-code + * BSD4.4 portable checksum routine + */ + +#ifdef __sparc_v9__ +#define STACKOFF 0x7ff+128 +#else +#define STACKOFF 64 +#endif + +#ifdef __KERNEL__ +#include +#include +#include +#else +#define ASI_P 0x80 +#define ASI_BLK_P 0xf0 +#define FRPS_FEF 0x04 +#define FPRS_DU 0x02 +#define FPRS_DL 0x01 +#endif +#define ASI_BLK_XOR (ASI_BLK_P ^ ASI_P) + +#define src o0 +#define dst o1 +#define len o2 +#define sum o3 +#define x1 g1 +#define x2 g2 +#define x3 g3 +#define x4 g4 +#define x5 g5 +#define x6 g7 +#define x7 o4 +#define x8 o5 + +/* Dobrou noc, SunSoft engineers. Spete sladce. + * This has a couple of tricks in and those + * tricks are UltraLinux trade secrets :)) + * Once AGAIN, the SunSoft engineers are caught + * asleep at the keyboard :)). + * The main loop does about 20 superscalar cycles + * per 64bytes checksummed/copied. + */ + +#define LDBLK(O0) \ + ldda [%src] %asi, %O0 /* Load Group */ + +#define STBLK \ + stda %f48, [%dst] ASI_BLK_P /* Store */ + +#define ST(fx,off) \ + std %fx, [%dst + off] /* Store */ + +#define SYNC \ + membar #Sync + + +#define DO_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14,DUMMY1,A0,A2,A4,A6,A8,A10,A12,A14,B14,DYMMY2,LOAD,STORE1,STORE2,STORE3,STORE4,STORE5,STORE6,STORE7,STORE8,DUMMY3,BRANCH...) \ + LOAD /* Load Group */; \ + faligndata %A14, %F0, %A14 /* FPA Group */; \ + inc %x5 /* IEU0 */; \ + STORE1 /* Store (optional) */; \ + faligndata %F0, %F2, %A0 /* FPA Group */; \ + srl %x5, 1, %x5 /* IEU0 */; \ + add %sum, %x4, %sum /* IEU1 */; \ + fpadd32 %F0, %f0, %F0 /* FPA Group */; \ + inc %x6 /* IEU0 */; \ + STORE2 /* Store (optional) */; \ + faligndata %F2, %F4, %A2 /* FPA Group */; \ + srl %x6, 1, %x6 /* IEU0 */; \ + add %sum, %x5, %sum /* IEU1 */; \ + fpadd32 %F2, %f2, %F2 /* FPA Group */; \ + add %src, 64, %src /* IEU0 */; \ + add %dst, 64, %dst /* IEU1 */; \ + fcmpgt32 %f0, %F0, %x1 /* FPM Group */; \ + inc %x7 /* IEU0 */; \ + STORE3 /* Store (optional) */; \ + faligndata %F4, %F6, %A4 /* FPA */; \ + srl %x7, 1, %x7 /* IEU0 Group */; \ + add %sum, %x6, %sum /* IEU1 */; \ + fpadd32 %F4, %f4, %F4 /* FPA */; \ + fcmpgt32 %f2, %F2, %x2 /* FPM Group */; \ + inc %x8 /* IEU0 */; \ + STORE4 /* Store (optional) */; \ + faligndata %F6, %F8, %A6 /* FPA */; \ + srl %x8, 1, %x8 /* IEU0 Group */; \ + add %sum, %x7, %sum /* IEU1 */; \ + fpadd32 %F6, %f6, %F6 /* FPA */; \ + fcmpgt32 %f4, %F4, %x3 /* FPM Group */; \ + inc %x1 /* IEU0 */; \ + STORE5 /* Store (optional) */; \ + faligndata %F8, %F10, %A8 /* FPA */; \ + srl %x1, 1, %x1 /* IEU0 Group */; \ + add %sum, %x8, %sum /* IEU1 */; \ + fpadd32 %F8, %f8, %F8 /* FPA */; \ + fcmpgt32 %f6, %F6, %x4 /* FPM Group */; \ + inc %x2 /* IEU0 */; \ + STORE6 /* Store (optional) */; \ + faligndata %F10, %F12, %A10 /* FPA */; \ + srl %x2, 1, %x2 /* IEU0 Group */; \ + add %sum, %x1, %sum /* IEU1 */; \ + fpadd32 %F10, %f10, %F10 /* FPA */; \ + fcmpgt32 %f8, %F8, %x5 /* FPM Group */; \ + inc %x3 /* IEU0 */; \ + STORE7 /* Store (optional) */; \ + faligndata %F12, %F14, %A12 /* FPA */; \ + srl %x3, 1, %x3 /* IEU0 Group */; \ + add %sum, %x2, %sum /* IEU1 */; \ + fpadd32 %F12, %f12, %F12 /* FPA */; \ + fcmpgt32 %f10, %F10, %x6 /* FPM Group */; \ + inc %x4 /* IEU0 */; \ + STORE8 /* Store (optional) */; \ + fmovd %F14, %B14 /* FPA */; \ + srl %x4, 1, %x4 /* IEU0 Group */; \ + add %sum, %x3, %sum /* IEU1 */; \ + fpadd32 %F14, %f14, %F14 /* FPA */; \ + fcmpgt32 %f12, %F12, %x7 /* FPM Group */; \ + subcc %len, 64, %len /* IEU1 */; \ + BRANCH /* CTI */; \ + fcmpgt32 %f14, %F14, %x8 /* FPM Group */; \ + +#define END_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB,S0,S1,S2,S3,T0,T1,U0,fz) \ + inc %x5 /* IEU0 Group */; \ + fpadd32 %f2, %f0, %S0 /* FPA */; \ + srl %x5, 1, %x5 /* IEU0 Group */; \ + add %sum, %x4, %sum /* IEU1 */; \ + fpadd32 %f6, %f4, %S1 /* FPA */; \ + inc %x6 /* IEU0 Group */; \ + add %sum, %x5, %sum /* IEU1 */; \ + fcmpgt32 %f0, %S0, %x1 /* FPM Group */; \ + srl %x6, 1, %x6 /* IEU0 */; \ + inc %x7 /* IEU1 */; \ + fpadd32 %f10, %f8, %S2 /* FPA */; \ + fcmpgt32 %f4, %S1, %x2 /* FPM Group */; \ + srl %x7, 1, %x7 /* IEU0 */; \ + add %sum, %x6, %sum /* IEU1 */; \ + fpadd32 %f14, %f12, %S3 /* FPA */; \ + inc %x8 /* IEU0 Group */; \ + add %sum, %x7, %sum /* IEU1 */; \ + fzero %fz /* FPA */; \ + fcmpgt32 %f8, %S2, %x3 /* FPM Group */; \ + srl %x8, 1, %x8 /* IEU0 */; \ + inc %x1 /* IEU1 */; \ + fpadd32 %S0, %S1, %T0 /* FPA */; \ + fcmpgt32 %f12, %S3, %x4 /* FPM Group */; \ + srl %x1, 1, %x1 /* IEU0 */; \ + add %sum, %x8, %sum /* IEU1 */; \ + fpadd32 %S2, %S3, %T1 /* FPA */; \ + inc %x2 /* IEU0 Group */; \ + add %sum, %x1, %sum /* IEU1 */; \ + fcmpgt32 %S0, %T0, %x5 /* FPM Group */; \ + srl %x2, 1, %x2 /* IEU0 */; \ + inc %x3 /* IEU1 */; \ + fcmpgt32 %S2, %T1, %x6 /* FPM Group */; \ + srl %x3, 1, %x3 /* IEU0 */; \ + add %sum, %x2, %sum /* IEU1 */; \ + inc %x4 /* IEU0 Group */; \ + add %sum, %x3, %sum /* IEU1 */; \ + fcmpgt32 %fz, %f2, %x7 /* FPM Group */; \ + srl %x4, 1, %x4 /* IEU0 */; \ + inc %x5 /* IEU1 */; \ + fpadd32 %T0, %T1, %U0 /* FPA */; \ + fcmpgt32 %fz, %f6, %x8 /* FPM Group */; \ + srl %x5, 1, %x5 /* IEU0 */; \ + add %sum, %x4, %sum /* IEU1 */; \ + inc %x6 /* IEU0 Group */; \ + add %sum, %x5, %sum /* IEU1 */; \ + fcmpgt32 %fz, %f10, %x1 /* FPM Group */; \ + srl %x6, 1, %x6 /* IEU0 */; \ + inc %x7 /* IEU1 */; \ + fcmpgt32 %fz, %f14, %x2 /* FPM Group */; \ + ba,pt %xcc, ett /* CTI */; \ + fmovd %FA, %FB /* FPA */; \ + +#define END_THE_TRICK1(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB) \ + END_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB,f48,f50,f52,f54,f56,f58,f60,f62) + +#define END_THE_TRICK2(S0,S1,S2,S3,T0,T1,U0,U1,V0,fz) \ + fpadd32 %U0, %U1, %V0 /* FPA Group */; \ + srl %x7, 1, %x7 /* IEU0 */; \ + add %sum, %x6, %sum /* IEU1 */; \ + std %V0, [%sp + STACKOFF] /* Store Group */; \ + inc %x8 /* IEU0 */; \ + sub %sum, %x7, %sum /* IEU1 */; \ + fcmpgt32 %fz, %S1, %x3 /* FPM Group */; \ + srl %x8, 1, %x8 /* IEU0 */; \ + inc %x1 /* IEU1 */; \ + fcmpgt32 %fz, %S3, %x4 /* FPM Group */; \ + srl %x1, 1, %x1 /* IEU0 */; \ + sub %sum, %x8, %sum /* IEU1 */; \ + ldx [%sp + STACKOFF], %x8 /* Load Group */; \ + inc %x2 /* IEU0 */; \ + sub %sum, %x1, %sum /* IEU1 */; \ + fcmpgt32 %fz, %T1, %x5 /* FPM Group */; \ + srl %x2, 1, %x2 /* IEU0 */; \ + inc %x3 /* IEU1 */; \ + fcmpgt32 %T0, %U0, %x6 /* FPM Group */; \ + srl %x3, 1, %x3 /* IEU0 */; \ + sub %sum, %x2, %sum /* IEU1 */; \ + inc %x4 /* IEU0 Group */; \ + sub %sum, %x3, %sum /* IEU1 */; \ + fcmpgt32 %fz, %U1, %x7 /* FPM Group */; \ + srl %x4, 1, %x4 /* IEU0 */; \ + inc %x5 /* IEU1 */; \ + fcmpgt32 %U0, %V0, %x1 /* FPM Group */; \ + srl %x5, 1, %x5 /* IEU0 */; \ + sub %sum, %x4, %sum /* IEU1 */; \ + fcmpgt32 %fz, %V0, %x2 /* FPM Group */; \ + inc %x6 /* IEU0 */; \ + sub %sum, %x5, %sum /* IEU1 */; \ + srl %x6, 1, %x6 /* IEU0 Group */; \ + inc %x7 /* IEU1 */; \ + srl %x7, 1, %x7 /* IEU0 Group */; \ + add %sum, %x6, %sum /* IEU1 */; \ + inc %x1 /* IEU0 Group */; \ + sub %sum, %x7, %sum /* IEU1 */; \ + srl %x1, 1, %x1 /* IEU0 Group */; \ + inc %x2 /* IEU1 */; \ + srl %x2, 1, %x2 /* IEU0 Group */; \ + add %sum, %x1, %sum /* IEU1 */; \ + sub %sum, %x2, %sum /* IEU0 Group */; \ + addcc %sum, %x8, %sum /* IEU Group */; \ + bcs,a,pn %xcc, 33f /* CTI */; \ + add %sum, 1, %sum /* IEU0 */; \ +33: /* That's it */; + + .text + .globl csum_partial_copy_vis + .align 32 +/* %asi should be either ASI_P or ASI_S for csum_partial_copy resp. csum_partial_copy_from_user */ +/* This assumes that !((%src^%dst)&3) && !((%src|%dst)&1) && %len >= 256 */ +csum_partial_copy_vis: + andcc %dst, 7, %g0 /* IEU1 Group */ + be,pt %icc, 4f /* CTI */ + and %dst, 0x38, %g3 /* IEU0 */ + mov 1, %g5 /* IEU0 Group */ + andcc %dst, 2, %g0 /* IEU1 */ + be,pt %icc, 1f /* CTI */ + and %dst, 4, %g7 /* IEU0 Group */ + lduha [%src] %asi, %g2 /* Load */ + sub %len, 2, %len /* IEU0 Group */ + add %dst, 2, %dst /* IEU1 */ + andcc %dst, 4, %g7 /* IEU1 Group */ + sll %g5, 16, %g5 /* IEU0 */ + sth %g2, [%dst - 2] /* Store Group */ + sll %g2, 16, %g2 /* IEU0 */ + add %src, 2, %src /* IEU1 */ + addcc %g2, %sum, %sum /* IEU1 Group */ + bcs,a,pn %icc, 1f /* CTI */ + add %sum, %g5, %sum /* IEU0 */ +1: lduwa [%src] %asi, %g2 /* Load */ + brz,a,pn %g7, 4f /* CTI+IEU1 Group */ + and %dst, 0x38, %g3 /* IEU0 */ + add %dst, 4, %dst /* IEU0 Group */ + sub %len, 4, %len /* IEU1 */ + addcc %g2, %sum, %sum /* IEU1 Group */ + bcs,a,pn %icc, 1f /* CTI */ + add %sum, 1, %sum /* IEU0 */ +1: and %dst, 0x38, %g3 /* IEU0 Group */ + stw %g2, [%dst - 4] /* Store */ + add %src, 4, %src /* IEU1 */ +4: +#ifdef __KERNEL__ + wr %g0, FPRS_FEF, %fprs /* LSU Group */ +#endif + mov %src, %g7 /* IEU1 Group */ + fzero %f48 /* FPA */ + alignaddr %src, %g0, %src /* Single Group */ + subcc %g7, %src, %g7 /* IEU1 Group */ + be,pt %xcc, 1f /* CTI */ + mov 0x40, %g1 /* IEU0 */ + lduwa [%src] %asi, %g2 /* Load Group */ + subcc %sum, %g2, %sum /* IEU1 Group+load stall */ + bcs,a,pn %icc, 1f /* CTI */ + sub %sum, 1, %sum /* IEU0 */ +1: srl %sum, 0, %sum /* IEU0 Group */ + clr %g5 /* IEU1 */ + brz,pn %g3, 3f /* CTI+IEU1 Group */ + sub %g1, %g3, %g1 /* IEU0 */ + ldda [%src] %asi, %f0 /* Load */ + clr %g3 /* IEU0 Group */ + andcc %dst, 8, %g0 /* IEU1 */ + be,pn %icc, 1f /* CTI */ + ldda [%src + 8] %asi, %f2 /* Load Group */ + add %src, 8, %src /* IEU0 */ + sub %len, 8, %len /* IEU1 */ + fpadd32 %f0, %f48, %f50 /* FPA */ + addcc %dst, 8, %dst /* IEU1 Group */ + faligndata %f0, %f2, %f16 /* FPA */ + fcmpgt32 %f48, %f50, %g3 /* FPM Group */ + fmovd %f2, %f0 /* FPA Group */ + ldda [%src + 8] %asi, %f2 /* Load */ + std %f16, [%dst - 8] /* Store */ + fmovd %f50, %f48 /* FPA */ +1: andcc %g1, 0x10, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + and %g1, 0x20, %g1 /* IEU0 */ + fpadd32 %f0, %f48, %f50 /* FPA */ + ldda [%src + 16] %asi, %f4 /* Load Group */ + add %src, 16, %src /* IEU0 */ + add %dst, 16, %dst /* IEU1 */ + faligndata %f0, %f2, %f16 /* FPA */ + fcmpgt32 %f48, %f50, %g5 /* FPM Group */ + sub %len, 16, %len /* IEU0 */ + inc %g3 /* IEU1 */ + std %f16, [%dst - 16] /* Store Group */ + fpadd32 %f2, %f50, %f48 /* FPA */ + srl %g3, 1, %o5 /* IEU0 */ + faligndata %f2, %f4, %f18 /* FPA Group */ + std %f18, [%dst - 8] /* Store */ + fcmpgt32 %f50, %f48, %g3 /* FPM Group */ + add %o5, %sum, %sum /* IEU0 */ + ldda [%src + 8] %asi, %f2 /* Load */ + fmovd %f4, %f0 /* FPA */ +1: brz,a,pn %g1, 4f /* CTI+IEU1 Group */ + rd %asi, %g2 /* LSU Group + 4 bubbles */ + inc %g5 /* IEU0 */ + fpadd32 %f0, %f48, %f50 /* FPA */ + ldda [%src + 16] %asi, %f4 /* Load Group */ + srl %g5, 1, %g5 /* IEU0 */ + add %dst, 32, %dst /* IEU1 */ + faligndata %f0, %f2, %f16 /* FPA */ + fcmpgt32 %f48, %f50, %o5 /* FPM Group */ + inc %g3 /* IEU0 */ + ldda [%src + 24] %asi, %f6 /* Load */ + srl %g3, 1, %g3 /* IEU0 Group */ + add %g5, %sum, %sum /* IEU1 */ + ldda [%src + 32] %asi, %f8 /* Load */ + fpadd32 %f2, %f50, %f48 /* FPA */ + faligndata %f2, %f4, %f18 /* FPA Group */ + sub %len, 32, %len /* IEU0 */ + std %f16, [%dst - 32] /* Store */ + fcmpgt32 %f50, %f48, %o4 /* FPM Group */ + inc %o5 /* IEU0 */ + add %g3, %sum, %sum /* IEU1 */ + fpadd32 %f4, %f48, %f50 /* FPA */ + faligndata %f4, %f6, %f20 /* FPA Group */ + srl %o5, 1, %o5 /* IEU0 */ + fcmpgt32 %f48, %f50, %g5 /* FPM Group */ + add %o5, %sum, %sum /* IEU0 */ + std %f18, [%dst - 24] /* Store */ + fpadd32 %f6, %f50, %f48 /* FPA */ + inc %o4 /* IEU0 Group */ + std %f20, [%dst - 16] /* Store */ + add %src, 32, %src /* IEU1 */ + faligndata %f6, %f8, %f22 /* FPA */ + fcmpgt32 %f50, %f48, %g3 /* FPM Group */ + srl %o4, 1, %o4 /* IEU0 */ + std %f22, [%dst - 8] /* Store */ + add %o4, %sum, %sum /* IEU0 Group */ +3: rd %asi, %g2 /* LSU Group + 4 bubbles */ +#ifdef __KERNEL__ +4: sethi %hi(vis0s), %g7 /* IEU0 Group */ +#else +4: rd %pc, %g7 /* LSU Group + 4 bubbles */ +#endif + inc %g5 /* IEU0 Group */ + and %src, 0x38, %o4 /* IEU1 */ + membar #StoreLoad /* LSU Group */ + srl %g5, 1, %g5 /* IEU0 */ + inc %g3 /* IEU1 */ + sll %o4, 8, %o4 /* IEU0 Group */ + sub %len, 0xc0, %len /* IEU1 */ + addcc %g5, %sum, %sum /* IEU1 Group */ + srl %g3, 1, %g3 /* IEU0 */ + add %g7, %o4, %g7 /* IEU0 Group */ + add %g3, %sum, %sum /* IEU1 */ +#ifdef __KERNEL__ + jmpl %g7 + %lo(vis0s), %g0 /* CTI+IEU1 Group */ +#else + jmpl %g7 + (vis0s - 4b), %g0 /* CTI+IEU1 Group */ +#endif + fzero %f32 /* FPA */ + + .align 2048 +vis0s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f62 /* FPA Group */ + faligndata %f0, %f2, %f48 /* FPA Group */ + fcmpgt32 %f32, %f2, %x1 /* FPM Group */ + fpadd32 %f0, %f62, %f0 /* FPA */ + fcmpgt32 %f32, %f4, %x2 /* FPM Group */ + faligndata %f2, %f4, %f50 /* FPA */ + fcmpgt32 %f62, %f0, %x3 /* FPM Group */ + faligndata %f4, %f6, %f52 /* FPA */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + inc %x1 /* IEU0 */ + faligndata %f6, %f8, %f54 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + srl %x1, 1, %x1 /* IEU0 */ + inc %x2 /* IEU1 */ + faligndata %f8, %f10, %f56 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + srl %x2, 1, %x2 /* IEU0 */ + add %sum, %x1, %sum /* IEU1 */ + faligndata %f10, %f12, %f58 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + inc %x3 /* IEU0 */ + add %sum, %x2, %sum /* IEU1 */ + faligndata %f12, %f14, %f60 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + srl %x3, 1, %x3 /* IEU0 */ + inc %x4 /* IEU1 */ + fmovd %f14, %f62 /* FPA */ + srl %x4, 1, %x4 /* IEU0 Group */ + add %sum, %x3, %sum /* IEU1 */ +vis0: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f48,f50,f52,f54,f56,f58,f60,f62,f62, + ,LDBLK(f32), STBLK,,,,,,,, + ,bcs,pn %icc, vis0e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f48,f50,f52,f54,f56,f58,f60,f62,f62, + ,LDBLK(f0), STBLK,,,,,,,, + ,bcs,pn %icc, vis0e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f48,f50,f52,f54,f56,f58,f60,f62,f62, + ,LDBLK(f16), STBLK,,,,,,,, + ,bcc,pt %icc, vis0) +vis0e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f48,f50,f52,f54,f56,f58,f60,f62,f32, + ,SYNC, STBLK,ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48), + ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e2) +vis0e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f48,f50,f52,f54,f56,f58,f60,f62,f0, + ,SYNC, STBLK,ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48), + ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e3) +vis0e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f48,f50,f52,f54,f56,f58,f60,f62,f16, + ,SYNC, STBLK,ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48), + ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e1) + .align 2048 +vis1s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 8, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fcmpgt32 %f32, %f2, %x2 /* FPM Group */ + faligndata %f2, %f4, %f48 /* FPA */ + fcmpgt32 %f32, %f4, %x3 /* FPM Group */ + faligndata %f4, %f6, %f50 /* FPA */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + faligndata %f6, %f8, %f52 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + inc %x2 /* IEU1 */ + faligndata %f8, %f10, %f54 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + srl %x2, 1, %x2 /* IEU0 */ + faligndata %f10, %f12, %f56 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + inc %x3 /* IEU0 */ + add %sum, %x2, %sum /* IEU1 */ + faligndata %f12, %f14, %f58 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + srl %x3, 1, %x3 /* IEU0 */ + inc %x4 /* IEU1 */ + fmovd %f14, %f60 /* FPA */ + srl %x4, 1, %x4 /* IEU0 Group */ + add %sum, %x3, %sum /* IEU1 */ +vis1: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f62,f48,f50,f52,f54,f56,f58,f60,f60, + ,LDBLK(f32), ,STBLK,,,,,,, + ,bcs,pn %icc, vis1e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f62,f48,f50,f52,f54,f56,f58,f60,f60, + ,LDBLK(f0), ,STBLK,,,,,,, + ,bcs,pn %icc, vis1e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f62,f48,f50,f52,f54,f56,f58,f60,f60, + ,LDBLK(f16), ,STBLK,,,,,,, + ,bcc,pt %icc, vis1) +vis1e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f62,f48,f50,f52,f54,f56,f58,f60,f32, + ,SYNC, ,STBLK,ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40), + ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e2) +vis1e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f62,f48,f50,f52,f54,f56,f58,f60,f0, + ,SYNC, ,STBLK,ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40), + ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e3) +vis1e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f62,f48,f50,f52,f54,f56,f58,f60,f16, + ,SYNC, ,STBLK,ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40), + ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e1) + .align 2048 +vis2s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 16, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + sub %dst, 64, %dst /* IEU0 */ + fzero %f2 /* FPA Group */ + fcmpgt32 %f32, %f4, %x3 /* FPM Group */ + faligndata %f4, %f6, %f48 /* FPA */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + faligndata %f6, %f8, %f50 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + faligndata %f8, %f10, %f52 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + faligndata %f10, %f12, %f54 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + inc %x3 /* IEU0 */ + faligndata %f12, %f14, %f56 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + srl %x3, 1, %x3 /* IEU0 */ + inc %x4 /* IEU1 */ + fmovd %f14, %f58 /* FPA */ + srl %x4, 1, %x4 /* IEU0 Group */ + add %sum, %x3, %sum /* IEU1 */ +vis2: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f60,f62,f48,f50,f52,f54,f56,f58,f58, + ,LDBLK(f32), ,,STBLK,,,,,, + ,bcs,pn %icc, vis2e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f60,f62,f48,f50,f52,f54,f56,f58,f58, + ,LDBLK(f0), ,,STBLK,,,,,, + ,bcs,pn %icc, vis2e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f60,f62,f48,f50,f52,f54,f56,f58,f58, + ,LDBLK(f16), ,,STBLK,,,,,, + ,bcc,pt %icc, vis2) +vis2e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f60,f62,f48,f50,f52,f54,f56,f58,f32, + ,SYNC, ,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96), + ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e2) +vis2e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f60,f62,f48,f50,f52,f54,f56,f58,f0, + ,SYNC, ,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96), + ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e3) +vis2e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f60,f62,f48,f50,f52,f54,f56,f58,f16, + ,SYNC, ,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96), + ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e1) + .align 2048 +vis3s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 24, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + sub %dst, 64, %dst /* IEU0 */ + fzero %f2 /* FPA Group */ + fzero %f4 /* FPA Group */ + fcmpgt32 %f32, %f6, %x4 /* FPM Group */ + faligndata %f6, %f8, %f48 /* FPA */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + faligndata %f8, %f10, %f50 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + faligndata %f10, %f12, %f52 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + faligndata %f12, %f14, %f54 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f56 /* FPA */ + inc %x4 /* IEU0 */ + srl %x4, 1, %x4 /* IEU0 Group */ +vis3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f58,f60,f62,f48,f50,f52,f54,f56,f56, + ,LDBLK(f32), ,,,STBLK,,,,, + ,bcs,pn %icc, vis3e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f58,f60,f62,f48,f50,f52,f54,f56,f56, + ,LDBLK(f0), ,,,STBLK,,,,, + ,bcs,pn %icc, vis3e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f58,f60,f62,f48,f50,f52,f54,f56,f56, + ,LDBLK(f16), ,,,STBLK,,,,, + ,bcc,pt %icc, vis3) +vis3e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f58,f60,f62,f48,f50,f52,f54,f56,f32, + ,SYNC, ,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88), + ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e2) +vis3e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f58,f60,f62,f48,f50,f52,f54,f56,f0, + ,SYNC, ,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88), + ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e3) +vis3e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f58,f60,f62,f48,f50,f52,f54,f56,f16, + ,SYNC, ,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88), + ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e1) + .align 2048 +vis4s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + add %src, 128 - 32, %src /* IEU0 Group */ + ldda [%src-128] %asi, %f0 /* Load Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + sub %dst, 64, %dst /* IEU0 */ + fzero %f2 /* FPA Group */ + fzero %f4 /* FPA Group */ + fzero %f6 /* FPA Group */ + clr %x4 /* IEU0 */ + fcmpgt32 %f32, %f8, %x5 /* FPM Group */ + faligndata %f8, %f10, %f48 /* FPA */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + faligndata %f10, %f12, %f50 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + faligndata %f12, %f14, %f52 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f54 /* FPA */ +vis4: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f56,f58,f60,f62,f48,f50,f52,f54,f54, + ,LDBLK(f32), ,,,,STBLK,,,, + ,bcs,pn %icc, vis4e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f56,f58,f60,f62,f48,f50,f52,f54,f54, + ,LDBLK(f0), ,,,,STBLK,,,, + ,bcs,pn %icc, vis4e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f56,f58,f60,f62,f48,f50,f52,f54,f54, + ,LDBLK(f16), ,,,,STBLK,,,, + ,bcc,pt %icc, vis4) +vis4e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f56,f58,f60,f62,f48,f50,f52,f54,f32, + ,SYNC, ,,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80), + ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e2) +vis4e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f56,f58,f60,f62,f48,f50,f52,f54,f0, + ,SYNC, ,,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80), + ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e3) +vis4e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f56,f58,f60,f62,f48,f50,f52,f54,f16, + ,SYNC, ,,,,STBLK,ST(f48,64),ST(f50,72),ST(f52,80), + ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e1) + .align 2048 +vis5s: add %src, 128 - 40, %src /* IEU0 Group */ + ldda [%src-88] %asi, %f10 /* Load Group */ + ldda [%src-80] %asi, %f12 /* Load Group */ + ldda [%src-72] %asi, %f14 /* Load Group */ + wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fmuld %f32, %f32, %f2 /* FPM */ + clr %x4 /* IEU0 */ + faddd %f32, %f32, %f4 /* FPA Group */ + fmuld %f32, %f32, %f6 /* FPM */ + clr %x5 /* IEU0 */ + faddd %f32, %f32, %f8 /* FPA Group */ + fcmpgt32 %f32, %f10, %x6 /* FPM Group */ + sub %dst, 64, %dst /* IEU0 */ + faligndata %f10, %f12, %f48 /* FPA */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + faligndata %f12, %f14, %f50 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f52 /* FPA */ +vis5: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f54,f56,f58,f60,f62,f48,f50,f52,f52, + ,LDBLK(f32), ,,,,,STBLK,,, + ,bcs,pn %icc, vis5e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f54,f56,f58,f60,f62,f48,f50,f52,f52, + ,LDBLK(f0), ,,,,,STBLK,,, + ,bcs,pn %icc, vis5e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f54,f56,f58,f60,f62,f48,f50,f52,f52, + ,LDBLK(f16), ,,,,,STBLK,,, + ,bcc,pt %icc, vis5) +vis5e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f54,f56,f58,f60,f62,f48,f50,f52,f32, + ,SYNC, ,,,,,STBLK,ST(f48,64),ST(f50,72), + ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e2) +vis5e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f54,f56,f58,f60,f62,f48,f50,f52,f0, + ,SYNC, ,,,,,STBLK,ST(f48,64),ST(f50,72), + ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e3) +vis5e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f54,f56,f58,f60,f62,f48,f50,f52,f16, + ,SYNC, ,,,,,STBLK,ST(f48,64),ST(f50,72), + ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e1) + .align 2048 +vis6s: add %src, 128 - 48, %src /* IEU0 Group */ + ldda [%src-80] %asi, %f12 /* Load Group */ + ldda [%src-72] %asi, %f14 /* Load Group */ + wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fmuld %f32, %f32, %f2 /* FPM */ + clr %x4 /* IEU0 */ + faddd %f32, %f32, %f4 /* FPA Group */ + fmuld %f32, %f32, %f6 /* FPM */ + clr %x5 /* IEU0 */ + faddd %f32, %f32, %f8 /* FPA Group */ + fmuld %f32, %f32, %f10 /* FPM */ + clr %x6 /* IEU0 */ + fcmpgt32 %f32, %f12, %x7 /* FPM Group */ + sub %dst, 64, %dst /* IEU0 */ + faligndata %f12, %f14, %f48 /* FPA */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + fmovd %f14, %f50 /* FPA */ +vis6: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f52,f54,f56,f58,f60,f62,f48,f50,f50, + ,LDBLK(f32), ,,,,,,STBLK,, + ,bcs,pn %icc, vis6e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f52,f54,f56,f58,f60,f62,f48,f50,f50, + ,LDBLK(f0), ,,,,,,STBLK,, + ,bcs,pn %icc, vis6e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f52,f54,f56,f58,f60,f62,f48,f50,f50, + ,LDBLK(f16), ,,,,,,STBLK,, + ,bcc,pt %icc, vis6) +vis6e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f52,f54,f56,f58,f60,f62,f48,f50,f32, + ,SYNC, ,,,,,,STBLK,ST(f48,64), + ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e2) +vis6e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f52,f54,f56,f58,f60,f62,f48,f50,f0, + ,SYNC, ,,,,,,STBLK,ST(f48,64), + ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e3) +vis6e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f52,f54,f56,f58,f60,f62,f48,f50,f16, + ,SYNC, ,,,,,,STBLK,ST(f48,64), + ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e1) + .align 2048 +vis7s: add %src, 128 - 56, %src /* IEU0 Group */ + ldda [%src-72] %asi, %f14 /* Load Group */ + wr %g2, ASI_BLK_XOR, %asi /* LSU Group */ + ldda [%src-64] %asi, %f16 /* Load Group */ + fmovd %f48, %f0 /* FPA Group */ + fmuld %f32, %f32, %f2 /* FPM */ + clr %x4 /* IEU0 */ + faddd %f32, %f32, %f4 /* FPA Group */ + fmuld %f32, %f32, %f6 /* FPM */ + clr %x5 /* IEU0 */ + faddd %f32, %f32, %f8 /* FPA Group */ + fmuld %f32, %f32, %f10 /* FPM */ + clr %x6 /* IEU0 */ + faddd %f32, %f32, %f12 /* FPA Group */ + clr %x7 /* IEU0 */ + fcmpgt32 %f32, %f14, %x8 /* FPM Group */ + sub %dst, 64, %dst /* IEU0 */ + fmovd %f14, %f48 /* FPA */ +vis7: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f50,f52,f54,f56,f58,f60,f62,f48,f48, + ,LDBLK(f32), ,,,,,,,STBLK, + ,bcs,pn %icc, vis7e1) + DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f50,f52,f54,f56,f58,f60,f62,f48,f48, + ,LDBLK(f0), ,,,,,,,STBLK, + ,bcs,pn %icc, vis7e2) + DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f50,f52,f54,f56,f58,f60,f62,f48,f48, + ,LDBLK(f16), ,,,,,,,STBLK, + ,bcc,pt %icc, vis7) +vis7e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30, + ,f50,f52,f54,f56,f58,f60,f62,f48,f32, + ,SYNC, ,,,,,,,STBLK, + ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e2) +vis7e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46, + ,f50,f52,f54,f56,f58,f60,f62,f48,f0, + ,SYNC, ,,,,,,,STBLK, + ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e3) +vis7e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14, + ,f50,f52,f54,f56,f58,f60,f62,f48,f16, + ,SYNC, ,,,,,,,STBLK, + ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e1) +e1: END_THE_TRICK1( f0,f2,f4,f6,f8,f10,f12,f14,f16,f6) +e2: END_THE_TRICK1( f16,f18,f20,f22,f24,f26,f28,f30,f32,f6) +e3: END_THE_TRICK1( f32,f34,f36,f38,f40,f42,f44,f46,f0,f6) +ett: rd %gsr, %x3 /* LSU Group+4bubbles */ + andcc %x3, 7, %x3 /* IEU1 Group */ + add %dst, 8, %dst /* IEU0 Group */ + bne,pn %icc, 1f /* CTI */ + fzero %f10 /* FPA */ + brz,a,pn %len, 2f /* CTI+IEU1 Group */ + std %f6, [%dst - 8] /* Store */ +1: rd %asi, %x4 /* LSU Group+4bubbles */ + sub %src, 64, %src /* IEU0 Group */ + cmp %len, 8 /* IEU1 */ + blu,pn %icc, 3f /* CTI */ + wr %x4, ASI_BLK_XOR, %asi /* LSU Group+4bubbles */ +1: ldda [%src] %asi, %f2 /* Load Group */ + fpadd32 %f10, %f2, %f12 /* FPA Group+load stall */ + add %src, 8, %src /* IEU0 */ + add %dst, 8, %dst /* IEU1 */ + faligndata %f6, %f2, %f14 /* FPA Group */ + fcmpgt32 %f10, %f12, %x5 /* FPM Group */ + std %f14, [%dst - 16] /* Store */ + fmovd %f2, %f6 /* FPA */ + fmovd %f12, %f10 /* FPA Group */ + sub %len, 8, %len /* IEU1 */ + fzero %f16 /* FPA Group - FPU nop */ + fzero %f18 /* FPA Group - FPU nop */ + inc %x5 /* IEU0 */ + srl %x5, 1, %x5 /* IEU0 Group (regdep) */ + cmp %len, 8 /* IEU1 */ + bgeu,pt %icc, 1b /* CTI */ + add %x5, %sum, %sum /* IEU0 Group */ +3: brz,a,pt %x3, 2f /* CTI+IEU1 */ + std %f6, [%dst - 8] /* Store Group */ + st %f7, [%dst - 8] /* Store Group */ + sub %dst, 4, %dst /* IEU0 */ + add %len, 4, %len /* IEU1 */ +2: +#ifdef __KERNEL__ + sub %sp, 8, %sp /* IEU0 Group */ +#endif + END_THE_TRICK2( f48,f50,f52,f54,f56,f58,f60,f10,f12,f62) + membar #Sync /* LSU Group */ +#ifdef __KERNEL__ + wr %g0, 0, %fprs /* LSU Group */ + add %sp, 8, %sp /* IEU0 Group */ +#endif +23: brnz,pn %len, 26f /* CTI+IEU1 Group */ +24: sllx %sum, 32, %g1 /* IEU0 */ +25: addcc %sum, %g1, %src /* IEU1 Group */ + srlx %src, 32, %src /* IEU0 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %src, 1, %src /* IEU1 */ +#ifndef __KERNEL__ +1: retl /* CTI Group brk forced */ + srl %src, 0, %src /* IEU0 */ +#else +1: sethi %uhi(PAGE_OFFSET), %g4 /* IEU0 Group */ + retl /* CTI Group brk forced */ + sllx %g4, 32, %g4 /* IEU0 */ +#endif +26: andcc %len, 8, %g0 /* IEU1 Group */ + be,pn %icc, 1f /* CTI */ + lduwa [%src] %asi, %g3 /* Load */ + lduwa [%src+4] %asi, %g2 /* Load Group */ + add %src, 8, %src /* IEU0 */ + add %dst, 8, %dst /* IEU1 */ + sllx %g3, 32, %g5 /* IEU0 Group */ + stw %g3, [%dst - 8] /* Store */ + or %g5, %g2, %g5 /* IEU0 Group */ + stw %g2, [%dst - 4] /* Store */ + addcc %g5, %sum, %sum /* IEU1 Group */ + bcs,a,pn %xcc, 1f /* CTI */ + add %sum, 1, %sum /* IEU0 */ +1: andcc %len, 4, %g0 /* IEU1 Group */ + be,a,pn %icc, 1f /* CTI */ + clr %g2 /* IEU0 */ + lduwa [%src] %asi, %g7 /* Load */ + add %src, 4, %src /* IEU0 Group */ + add %dst, 4, %dst /* IEU1 */ + sllx %g7, 32, %g2 /* IEU0 Group */ + stw %g7, [%dst - 4] /* Store */ +1: andcc %len, 2, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o4 /* IEU0 Group */ + lduha [%src] %asi, %g7 /* Load */ + add %src, 2, %src /* IEU1 */ + add %dst, 2, %dst /* IEU0 Group */ + sll %g7, 16, %o4 /* IEU0 Group */ + sth %g7, [%dst - 2] /* Store */ +1: andcc %len, 1, %g0 /* IEU1 */ + be,a,pn %icc, 1f /* CTI */ + clr %o5 /* IEU0 Group */ + lduba [%src] %asi, %g7 /* Load */ + sll %g7, 8, %o5 /* IEU0 Group */ + stb %g7, [%dst] /* Store */ +1: or %g2, %o4, %o4 /* IEU1 */ + or %o5, %o4, %o4 /* IEU0 Group (regdep) */ + addcc %o4, %sum, %sum /* IEU1 Group (regdep) */ + bcs,a,pn %xcc, 1f /* CTI */ + add %sum, 1, %sum /* IEU0 */ +1: ba,pt %xcc, 25b /* CTI Group */ + sllx %sum, 32, %g1 /* IEU0 */ + +#ifdef __KERNEL__ +end: + + .section __ex_table + .align 8 + .xword csum_partial_copy_vis, 0, end, cpc_handler +#endif diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/VISmemset.S linux/arch/sparc64/lib/VISmemset.S --- v2.1.50/linux/arch/sparc64/lib/VISmemset.S Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/lib/VISmemset.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: VISmemset.S,v 1.4 1997/07/02 19:00:39 jj Exp $ +/* $Id: VISmemset.S,v 1.6 1997/08/08 08:34:13 jj Exp $ * VISmemset.S: High speed memset operations utilizing the UltraSparc * Visual Instruction Set. * @@ -172,10 +172,17 @@ #ifdef __KERNEL__ wr %g0, 0, %fprs #endif - membar #Sync + membar #StoreLoad | #StoreStore 9: andcc %o2, 0x78, %g5 be,pn %xcc, 13f andcc %o2, 7, %o2 +#ifdef __KERNEL__ +14: srl %g5, 1, %o3 + sethi %hi(13f), %o4 + sub %o4, %o3, %o4 + jmpl %o4 + %lo(13f), %g0 + add %o0, %g5, %o0 +#else 14: rd %pc, %o4 #ifdef REGS_64BIT srl %g5, 1, %o3 @@ -185,6 +192,7 @@ #endif jmpl %o4 + (13f - 14b), %g0 add %o0, %g5, %o0 +#endif 12: SET_BLOCKS(%o0, 0x68, %o1) SET_BLOCKS(%o0, 0x48, %o1) SET_BLOCKS(%o0, 0x28, %o1) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.1.50/linux/arch/sparc64/lib/blockops.S Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/lib/blockops.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.10 1997/06/24 17:29:10 jj Exp $ +/* $Id: blockops.S,v 1.11 1997/07/29 09:35:36 davem Exp $ * arch/sparc64/lib/blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -15,7 +15,7 @@ wr %g0, FPRS_FEF, %fprs ! FPU Group ldd [%o1], %f48 ! Load Group wr %g0, ASI_BLK_P, %asi ! LSU Group - membar #StoreStore | #LoadStore ! LSU Group + membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group mov 32, %g2 ! IEU0 Group /* Cannot perform real arithmatic on the pattern, that can @@ -36,7 +36,7 @@ subcc %g2, 1, %g2 ! IEU1 Group bne,pt %icc, 1b ! CTI add %o0, 0x100, %o0 ! IEU0 - membar #Sync ! LSU Group + membar #StoreLoad | #StoreStore ! LSU Group jmpl %o7 + 0x8, %g0 ! CTI Group brk forced wr %g0, 0, %fprs ! FPU Group @@ -56,7 +56,7 @@ faddd %f0, %f2, %f12 ! FPA Group fmuld %f0, %f2, %f14 ! FPM wr %g0, ASI_BLK_P, %asi ! LSU Group - membar #StoreStore | #LoadStore ! LSU Group + membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group 1: stda %f0, [%o0 + 0x00] %asi ! Store Group stda %f0, [%o0 + 0x40] %asi ! Store Group stda %f0, [%o0 + 0x80] %asi ! Store Group @@ -65,6 +65,6 @@ subcc %g1, 1, %g1 ! IEU1 bne,pt %icc, 1b ! CTI add %o0, 0x100, %o0 ! IEU0 Group - membar #Sync ! LSU Group + membar #StoreLoad | #StoreStore ! LSU Group jmpl %o7 + 0x8, %g0 ! CTI Group brk forced wr %g0, 0, %fprs ! FPU Group diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S --- v2.1.50/linux/arch/sparc64/lib/checksum.S Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/lib/checksum.S Sat Aug 16 10:00:22 1997 @@ -23,456 +23,456 @@ * are two fold. Firstly, they cannot pair with jack shit, * and also they only add in the 32-bit carry condition bit * into the accumulated sum. The following is much better. - * - * This should run at max bandwidth for ecache hits, a better - * technique is to use VIS and fpu operations. This is already - * done for csum_partial, needs to be written for the copy stuff - * still. + * For larger chunks we use VIS code, which is faster ;) */ - .text - .globl __csum_partial_copy_start, __csum_partial_copy_end -__csum_partial_copy_start: +#define src o0 +#define dst o1 +#define len o2 +#define sum o3 + .text /* I think I have an erection... Once _AGAIN_ the SunSoft * engineers are caught asleep at the keyboard, tsk tsk... */ -#define CSUMCOPY_ECACHE_LOAD(src, off, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldxa [src + off + 0x00] %asi, t0; \ - ldxa [src + off + 0x08] %asi, t1; \ - ldxa [src + off + 0x10] %asi, t2; \ - ldxa [src + off + 0x18] %asi, t3; \ - ldxa [src + off + 0x20] %asi, t4; \ - ldxa [src + off + 0x28] %asi, t5; \ - ldxa [src + off + 0x30] %asi, t6; \ - ldxa [src + off + 0x38] %asi, t7; \ +#define CSUMCOPY_ECACHE_LOAD(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldxa [%src + off + 0x00] %asi, t0; \ + ldxa [%src + off + 0x08] %asi, t1; \ + ldxa [%src + off + 0x10] %asi, t2; \ + ldxa [%src + off + 0x18] %asi, t3; \ + ldxa [%src + off + 0x20] %asi, t4; \ + ldxa [%src + off + 0x28] %asi, t5; \ + ldxa [%src + off + 0x30] %asi, t6; \ + ldxa [%src + off + 0x38] %asi, t7; \ nop; nop; /* DO NOT TOUCH THIS!!!!! */ -#define CSUMCOPY_EC_STALIGNED_LDNXT(src, dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)\ - stx t0, [dest + off - 0x40]; \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STALIGNED_LDNXT(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + stx t0, [%dst + off - 0x40]; \ + addcc %sum, t0, %sum; \ bcc,pt %xcc, 11f; \ - ldxa [src + off + 0x00] %asi, t0; \ - add sum, 1, sum; \ -11: stx t1, [dest + off - 0x38]; \ - addcc sum, t1, sum; \ + ldxa [%src + off + 0x00] %asi, t0; \ + add %sum, 1, %sum; \ +11: stx t1, [%dst + off - 0x38]; \ + addcc %sum, t1, %sum; \ bcc,pt %xcc, 12f; \ - ldxa [src + off + 0x08] %asi, t1; \ - add sum, 1, sum; \ -12: stx t2, [dest + off - 0x30]; \ - addcc sum, t2, sum; \ + ldxa [%src + off + 0x08] %asi, t1; \ + add %sum, 1, %sum; \ +12: stx t2, [%dst + off - 0x30]; \ + addcc %sum, t2, %sum; \ bcc,pt %xcc, 13f; \ - ldxa [src + off + 0x10] %asi, t2; \ - add sum, 1, sum; \ -13: stx t3, [dest + off - 0x28]; \ - addcc sum, t3, sum; \ + ldxa [%src + off + 0x10] %asi, t2; \ + add %sum, 1, %sum; \ +13: stx t3, [%dst + off - 0x28]; \ + addcc %sum, t3, %sum; \ bcc,pt %xcc, 14f; \ - ldxa [src + off + 0x18] %asi, t3; \ - add sum, 1, sum; \ -14: stx t4, [dest + off - 0x20]; \ - addcc sum, t4, sum; \ + ldxa [%src + off + 0x18] %asi, t3; \ + add %sum, 1, %sum; \ +14: stx t4, [%dst + off - 0x20]; \ + addcc %sum, t4, %sum; \ bcc,pt %xcc, 15f; \ - ldxa [src + off + 0x20] %asi, t4; \ - add sum, 1, sum; \ -15: stx t5, [dest + off - 0x18]; \ - addcc sum, t5, sum; \ + ldxa [%src + off + 0x20] %asi, t4; \ + add %sum, 1, %sum; \ +15: stx t5, [%dst + off - 0x18]; \ + addcc %sum, t5, %sum; \ bcc,pt %xcc, 16f; \ - ldxa [src + off + 0x28] %asi, t5; \ - add sum, 1, sum; \ -16: stx t6, [dest + off - 0x10]; \ - addcc sum, t6, sum; \ + ldxa [%src + off + 0x28] %asi, t5; \ + add %sum, 1, %sum; \ +16: stx t6, [%dst + off - 0x10]; \ + addcc %sum, t6, %sum; \ bcc,pt %xcc, 17f; \ - ldxa [src + off + 0x30] %asi, t6; \ - add sum, 1, sum; \ -17: stx t7, [dest + off - 0x08]; \ - addcc sum, t7, sum; \ + ldxa [%src + off + 0x30] %asi, t6; \ + add %sum, 1, %sum; \ +17: stx t7, [%dst + off - 0x08]; \ + addcc %sum, t7, %sum; \ bcc,pt %xcc, 18f; \ - ldxa [src + off + 0x38] %asi, t7; \ - add sum, 1, sum; \ + ldxa [%src + off + 0x38] %asi, t7; \ + add %sum, 1, %sum; \ 18: -#define CSUMCOPY_EC_STUNALIGN_LDNXT(src, dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7)\ - stw t0, [dest + off - 0x3c]; \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STUNALIGN_LDNXT(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + stw t0, [%dst + off - 0x3c]; \ + addcc %sum, t0, %sum; \ srlx t0, 32, t0; \ - stw t0, [dest + off - 0x40]; \ + stw t0, [%dst + off - 0x40]; \ bcc,pt %xcc, 21f; \ - ldxa [src + off + 0x00] %asi, t0; \ - add sum, 1, sum; \ -21: stw t1, [dest + off - 0x34]; \ - addcc sum, t1, sum; \ + ldxa [%src + off + 0x00] %asi, t0; \ + add %sum, 1, %sum; \ +21: stw t1, [%dst + off - 0x34]; \ + addcc %sum, t1, %sum; \ srlx t1, 32, t1; \ - stw t1, [dest + off - 0x38]; \ + stw t1, [%dst + off - 0x38]; \ bcc,pt %xcc, 22f; \ - ldxa [src + off + 0x08] %asi, t1; \ - add sum, 1, sum; \ -22: stw t2, [dest + off - 0x2c]; \ - addcc sum, t2, sum; \ + ldxa [%src + off + 0x08] %asi, t1; \ + add %sum, 1, %sum; \ +22: stw t2, [%dst + off - 0x2c]; \ + addcc %sum, t2, %sum; \ srlx t2, 32, t2; \ - stw t2, [dest + off - 0x30]; \ + stw t2, [%dst + off - 0x30]; \ bcc,pt %xcc, 23f; \ - ldxa [src + off + 0x10] %asi, t2; \ - add sum, 1, sum; \ -23: stw t3, [dest + off - 0x24]; \ - addcc sum, t3, sum; \ + ldxa [%src + off + 0x10] %asi, t2; \ + add %sum, 1, %sum; \ +23: stw t3, [%dst + off - 0x24]; \ + addcc %sum, t3, %sum; \ srlx t3, 32, t3; \ - stw t3, [dest + off - 0x28]; \ + stw t3, [%dst + off - 0x28]; \ bcc,pt %xcc, 24f; \ - ldxa [src + off + 0x18] %asi, t3; \ - add sum, 1, sum; \ -24: stw t4, [dest + off - 0x1c]; \ - addcc sum, t4, sum; \ + ldxa [%src + off + 0x18] %asi, t3; \ + add %sum, 1, %sum; \ +24: stw t4, [%dst + off - 0x1c]; \ + addcc %sum, t4, %sum; \ srlx t4, 32, t4; \ - stw t4, [dest + off - 0x20]; \ + stw t4, [%dst + off - 0x20]; \ bcc,pt %xcc, 25f; \ - ldxa [src + off + 0x20] %asi, t4; \ - add sum, 1, sum; \ -25: stw t5, [dest + off - 0x14]; \ - addcc sum, t5, sum; \ + ldxa [%src + off + 0x20] %asi, t4; \ + add %sum, 1, %sum; \ +25: stw t5, [%dst + off - 0x14]; \ + addcc %sum, t5, %sum; \ srlx t5, 32, t5; \ - stw t5, [dest + off - 0x18]; \ + stw t5, [%dst + off - 0x18]; \ bcc,pt %xcc, 26f; \ - ldxa [src + off + 0x28] %asi, t5; \ - add sum, 1, sum; \ -26: stw t6, [dest + off - 0x0c]; \ - addcc sum, t6, sum; \ + ldxa [%src + off + 0x28] %asi, t5; \ + add %sum, 1, %sum; \ +26: stw t6, [%dst + off - 0x0c]; \ + addcc %sum, t6, %sum; \ srlx t6, 32, t6; \ - stw t6, [dest + off - 0x10]; \ + stw t6, [%dst + off - 0x10]; \ bcc,pt %xcc, 27f; \ - ldxa [src + off + 0x30] %asi, t6; \ - add sum, 1, sum; \ -27: stw t7, [dest + off - 0x04]; \ - addcc sum, t7, sum; \ + ldxa [%src + off + 0x30] %asi, t6; \ + add %sum, 1, %sum; \ +27: stw t7, [%dst + off - 0x04]; \ + addcc %sum, t7, %sum; \ srlx t7, 32, t7; \ - stw t7, [dest + off - 0x08]; \ + stw t7, [%dst + off - 0x08]; \ bcc,pt %xcc, 28f; \ - ldxa [src + off + 0x38] %asi, t7; \ - add sum, 1, sum; \ + ldxa [%src + off + 0x38] %asi, t7; \ + add %sum, 1, %sum; \ 28: -#define CSUMCOPY_EC_STALIGNED(dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7) \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STALIGNED(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + addcc %sum, t0, %sum; \ bcc,pt %xcc, 31f; \ - stx t0, [dest + off + 0x00]; \ - add sum, 1, sum; \ -31: addcc sum, t1, sum; \ + stx t0, [%dst + off + 0x00]; \ + add %sum, 1, %sum; \ +31: addcc %sum, t1, %sum; \ bcc,pt %xcc, 32f; \ - stx t1, [dest + off + 0x08]; \ - add sum, 1, sum; \ -32: addcc sum, t2, sum; \ + stx t1, [%dst + off + 0x08]; \ + add %sum, 1, %sum; \ +32: addcc %sum, t2, %sum; \ bcc,pt %xcc, 33f; \ - stx t2, [dest + off + 0x10]; \ - add sum, 1, sum; \ -33: addcc sum, t3, sum; \ + stx t2, [%dst + off + 0x10]; \ + add %sum, 1, %sum; \ +33: addcc %sum, t3, %sum; \ bcc,pt %xcc, 34f; \ - stx t3, [dest + off + 0x18]; \ - add sum, 1, sum; \ -34: addcc sum, t4, sum; \ + stx t3, [%dst + off + 0x18]; \ + add %sum, 1, %sum; \ +34: addcc %sum, t4, %sum; \ bcc,pt %xcc, 35f; \ - stx t4, [dest + off + 0x20]; \ - add sum, 1, sum; \ -35: addcc sum, t5, sum; \ + stx t4, [%dst + off + 0x20]; \ + add %sum, 1, %sum; \ +35: addcc %sum, t5, %sum; \ bcc,pt %xcc, 36f; \ - stx t5, [dest + off + 0x28]; \ - add sum, 1, sum; \ -36: addcc sum, t6, sum; \ + stx t5, [%dst + off + 0x28]; \ + add %sum, 1, %sum; \ +36: addcc %sum, t6, %sum; \ bcc,pt %xcc, 37f; \ - stx t6, [dest + off + 0x30]; \ - add sum, 1, sum; \ -37: addcc sum, t7, sum; \ + stx t6, [%dst + off + 0x30]; \ + add %sum, 1, %sum; \ +37: addcc %sum, t7, %sum; \ bcc,pt %xcc, 38f; \ - stx t7, [dest + off + 0x38]; \ - add sum, 1, sum; \ + stx t7, [%dst + off + 0x38]; \ + add %sum, 1, %sum; \ 38: -#define CSUMCOPY_EC_STUNALIGN(dest, off, sum, t0, t1, t2, t3, t4, t5, t6, t7) \ - stw t0, [dest + off + 0x04]; \ - addcc sum, t0, sum; \ +#define CSUMCOPY_EC_STUNALIGN(off, t0, t1, t2, t3, t4, t5, t6, t7) \ + stw t0, [%dst + off + 0x04]; \ + addcc %sum, t0, %sum; \ srlx t0, 32, t0; \ bcc,pt %xcc, 41f; \ - stw t0, [dest + off + 0x00]; \ - add sum, 1, sum; \ -41: stw t1, [dest + off + 0x0c]; \ - addcc sum, t1, sum; \ + stw t0, [%dst + off + 0x00]; \ + add %sum, 1, %sum; \ +41: stw t1, [%dst + off + 0x0c]; \ + addcc %sum, t1, %sum; \ srlx t1, 32, t1; \ bcc,pt %xcc, 42f; \ - stw t1, [dest + off + 0x08]; \ - add sum, 1, sum; \ -42: stw t2, [dest + off + 0x14]; \ - addcc sum, t2, sum; \ + stw t1, [%dst + off + 0x08]; \ + add %sum, 1, %sum; \ +42: stw t2, [%dst + off + 0x14]; \ + addcc %sum, t2, %sum; \ srlx t2, 32, t2; \ bcc,pt %xcc, 43f; \ - stw t2, [dest + off + 0x10]; \ - add sum, 1, sum; \ -43: stw t3, [dest + off + 0x1c]; \ - addcc sum, t3, sum; \ + stw t2, [%dst + off + 0x10]; \ + add %sum, 1, %sum; \ +43: stw t3, [%dst + off + 0x1c]; \ + addcc %sum, t3, %sum; \ srlx t3, 32, t3; \ bcc,pt %xcc, 44f; \ - stw t3, [dest + off + 0x18]; \ - add sum, 1, sum; \ -44: stw t4, [dest + off + 0x24]; \ - addcc sum, t4, sum; \ + stw t3, [%dst + off + 0x18]; \ + add %sum, 1, %sum; \ +44: stw t4, [%dst + off + 0x24]; \ + addcc %sum, t4, %sum; \ srlx t4, 32, t4; \ bcc,pt %xcc, 45f; \ - stw t4, [dest + off + 0x20]; \ - add sum, 1, sum; \ -45: stw t5, [dest + off + 0x2c]; \ - addcc sum, t5, sum; \ + stw t4, [%dst + off + 0x20]; \ + add %sum, 1, %sum; \ +45: stw t5, [%dst + off + 0x2c]; \ + addcc %sum, t5, %sum; \ srlx t5, 32, t5; \ bcc,pt %xcc, 46f; \ - stw t5, [dest + off + 0x28]; \ - add sum, 1, sum; \ -46: stw t6, [dest + off + 0x34]; \ - addcc sum, t6, sum; \ + stw t5, [%dst + off + 0x28]; \ + add %sum, 1, %sum; \ +46: stw t6, [%dst + off + 0x34]; \ + addcc %sum, t6, %sum; \ srlx t6, 32, t6; \ bcc,pt %xcc, 47f; \ - stw t6, [dest + off + 0x30]; \ - add sum, 1, sum; \ -47: stw t7, [dest + off + 0x3c]; \ - addcc sum, t7, sum; \ + stw t6, [%dst + off + 0x30]; \ + add %sum, 1, %sum; \ +47: stw t7, [%dst + off + 0x3c]; \ + addcc %sum, t7, %sum; \ srlx t7, 32, t7; \ bcc,pt %xcc, 48f; \ - stw t7, [dest + off + 0x38]; \ - add sum, 1, sum; \ + stw t7, [%dst + off + 0x38]; \ + add %sum, 1, %sum; \ 48: -#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1) \ - ldxa [src - off - 0x08] %asi, t0; \ - ldxa [src - off - 0x00] %asi, t1; \ +#define CSUMCOPY_LASTCHUNK(off, t0, t1) \ + ldxa [%src - off - 0x08] %asi, t0; \ + ldxa [%src - off - 0x00] %asi, t1; \ nop; nop; \ - addcc t0, sum, sum; \ - stw t0, [dst - off - 0x04]; \ + addcc t0, %sum, %sum; \ + stw t0, [%dst - off - 0x04]; \ srlx t0, 32, t0; \ bcc,pt %xcc, 51f; \ - stw t0, [dst - off - 0x08]; \ - add sum, 1, sum; \ -51: addcc t1, sum, sum; \ - stw t1, [dst - off + 0x04]; \ + stw t0, [%dst - off - 0x08]; \ + add %sum, 1, %sum; \ +51: addcc t1, %sum, %sum; \ + stw t1, [%dst - off + 0x04]; \ srlx t1, 32, t1; \ bcc,pt %xcc, 52f; \ - stw t1, [dst - off - 0x00]; \ - add sum, 1, sum; \ + stw t1, [%dst - off - 0x00]; \ + add %sum, 1, %sum; \ 52: +cpc_start: cc_end_cruft: - andcc %o3, 8, %g0 ! IEU1 Group + andcc %g7, 8, %g0 ! IEU1 Group be,pn %icc, 1f ! CTI - and %o3, 4, %g5 ! IEU0 - ldxa [%o0 + 0x00] %asi, %g2 ! Load Group - add %o1, 8, %o1 ! IEU0 - add %o0, 8, %o0 ! IEU1 - addcc %g2, %g7, %g7 ! IEU1 Group + 2 bubbles - stw %g2, [%o1 - 0x04] ! Store + and %g7, 4, %g5 ! IEU0 + ldxa [%src + 0x00] %asi, %g2 ! Load Group + add %dst, 8, %dst ! IEU0 + add %src, 8, %src ! IEU1 + addcc %g2, %sum, %sum ! IEU1 Group + 2 bubbles + stw %g2, [%dst - 0x04] ! Store srlx %g2, 32, %g2 ! IEU0 bcc,pt %xcc, 1f ! CTI Group - stw %g2, [%o1 - 0x08] ! Store - add %g7, 1, %g7 ! IEU0 + stw %g2, [%dst - 0x08] ! Store + add %sum, 1, %sum ! IEU0 1: brz,pt %g5, 1f ! CTI Group clr %g2 ! IEU0 - lduwa [%o0 + 0x00] %asi, %g2 ! Load - add %o1, 4, %o1 ! IEU0 Group - add %o0, 4, %o0 ! IEU1 - stw %g2, [%o1 - 0x04] ! Store Group + 2 bubbles + lduwa [%src + 0x00] %asi, %g2 ! Load + add %dst, 4, %dst ! IEU0 Group + add %src, 4, %src ! IEU1 + stw %g2, [%dst - 0x04] ! Store Group + 2 bubbles sllx %g2, 32, %g2 ! IEU0 -1: andcc %o3, 2, %g0 ! IEU1 +1: andcc %g7, 2, %g0 ! IEU1 be,pn %icc, 1f ! CTI Group clr %o4 ! IEU1 - lduha [%o0 + 0x00] %asi, %o4 ! Load - add %o0, 2, %o0 ! IEU0 Group - add %o1, 2, %o1 ! IEU1 - sth %o4, [%o1 - 0x2] ! Store Group + 2 bubbles + lduha [%src + 0x00] %asi, %o4 ! Load + add %src, 2, %src ! IEU0 Group + add %dst, 2, %dst ! IEU1 + sth %o4, [%dst - 0x2] ! Store Group + 2 bubbles sll %o4, 16, %o4 ! IEU0 -1: andcc %o3, 1, %g0 ! IEU1 +1: andcc %g7, 1, %g0 ! IEU1 be,pn %icc, 1f ! CTI Group clr %o5 ! IEU0 - lduba [%o0 + 0x00] %asi, %o5 ! Load - stb %o5, [%o1 + 0x00] ! Store Group + 2 bubbles + lduba [%src + 0x00] %asi, %o5 ! Load + stb %o5, [%dst + 0x00] ! Store Group + 2 bubbles sll %o5, 8, %o5 ! IEU0 1: or %g2, %o4, %o4 ! IEU1 or %o5, %o4, %o4 ! IEU0 Group - addcc %o4, %g7, %g7 ! IEU1 + addcc %o4, %sum, %sum ! IEU1 bcc,pt %xcc, ccfold ! CTI sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 Group b,pt %xcc, ccfold ! CTI - add %g7, 1, %g7 ! IEU1 + add %sum, 1, %sum ! IEU1 cc_fixit: bl,a,pn %icc, ccte ! CTI - andcc %g1, 0xf, %o3 ! IEU1 Group - andcc %o0, 1, %g0 ! IEU1 Group - bne,pn %icc, ccslow ! CTI - andcc %o0, 2, %g0 ! IEU1 Group + andcc %len, 0xf, %g7 ! IEU1 Group + andcc %src, 2, %g0 ! IEU1 Group be,pn %icc, 1f ! CTI - andcc %o0, 0x4, %g0 ! IEU1 Group - lduha [%o0 + 0x00] %asi, %g4 ! Load - sub %g1, 2, %g1 ! IEU0 - add %o0, 2, %o0 ! IEU0 Group - add %o1, 2, %o1 ! IEU1 + andcc %src, 0x4, %g0 ! IEU1 Group + lduha [%src + 0x00] %asi, %g4 ! Load + sub %len, 2, %len ! IEU0 + add %src, 2, %src ! IEU0 Group + add %dst, 2, %dst ! IEU1 sll %g4, 16, %g3 ! IEU0 Group + 1 bubble - addcc %g3, %g7, %g7 ! IEU1 + addcc %g3, %sum, %sum ! IEU1 bcc,pt %xcc, 0f ! CTI - srl %g7, 16, %g3 ! IEU0 Group + srl %sum, 16, %g3 ! IEU0 Group add %g3, 1, %g3 ! IEU0 4 clocks (mispredict) -0: andcc %o0, 0x4, %g0 ! IEU1 Group - sth %g4, [%o1 - 0x2] ! Store - sll %g7, 16, %g7 ! IEU0 +0: andcc %src, 0x4, %g0 ! IEU1 Group + sth %g4, [%dst - 0x2] ! Store + sll %sum, 16, %sum ! IEU0 sll %g3, 16, %g3 ! IEU0 Group - srl %g7, 16, %g7 ! IEU0 Group - or %g3, %g7, %g7 ! IEU0 Group (regdep) + srl %sum, 16, %sum ! IEU0 Group + or %g3, %sum, %sum ! IEU0 Group (regdep) 1: be,pt %icc, cc_dword_aligned ! CTI - andn %g1, 0xff, %g2 ! IEU1 - lduwa [%o0 + 0x00] %asi, %g4 ! Load Group - sub %g1, 4, %g1 ! IEU0 - add %o0, 4, %o0 ! IEU1 - add %o1, 4, %o1 ! IEU0 Group - addcc %g4, %g7, %g7 ! IEU1 Group + 1 bubble - stw %g4, [%o1 - 0x4] ! Store + andn %len, 0xff, %g2 ! IEU1 + lduwa [%src + 0x00] %asi, %g4 ! Load Group + sub %len, 4, %len ! IEU0 + add %src, 4, %src ! IEU1 + add %dst, 4, %dst ! IEU0 Group + addcc %g4, %sum, %sum ! IEU1 Group + 1 bubble + stw %g4, [%dst - 0x4] ! Store bcc,pt %xcc, cc_dword_aligned ! CTI - andn %g1, 0xff, %g2 ! IEU0 Group + andn %len, 0xff, %g2 ! IEU0 Group b,pt %xcc, cc_dword_aligned ! CTI 4 clocks (mispredict) - add %g7, 1, %g7 ! IEU0 + add %sum, 1, %sum ! IEU0 .align 32 - .globl __csum_partial_copy_sparc_generic, csum_partial_copy -csum_partial_copy: -__csum_partial_copy_sparc_generic: /* %o0=src, %o1=dest, %g1=len, %g7=sum */ - xorcc %o0, %o1, %o4 ! IEU1 Group - srl %g7, 0, %g7 ! IEU0 + .globl csum_partial_copy_sparc64 +csum_partial_copy_sparc64: /* %o0=src, %o1=dest, %o2=len, %o3=sum */ + xorcc %src, %dst, %o4 ! IEU1 Group + srl %sum, 0, %sum ! IEU0 andcc %o4, 3, %g0 ! IEU1 Group - srl %g1, 0, %g1 ! IEU0 + srl %len, 0, %len ! IEU0 bne,pn %icc, ccslow ! CTI - andcc %o0, 7, %g0 ! IEU1 Group + andcc %src, 1, %g0 ! IEU1 Group + bne,pn %icc, ccslow ! CTI + cmp %len, 256 ! IEU1 Group + bgeu,pt %icc, csum_partial_copy_vis ! CTI + andcc %src, 7, %g0 ! IEU1 Group be,pt %icc, cc_dword_aligned ! CTI - andn %g1, 0xff, %g2 ! IEU0 + andn %len, 0xff, %g2 ! IEU0 b,pt %xcc, cc_fixit ! CTI Group - cmp %g1, 6 ! IEU1 + cmp %len, 6 ! IEU1 cc_dword_aligned: brz,pn %g2, 3f ! CTI Group - andcc %o1, 4, %g0 ! IEU1 Group (brz uses IEU1) + andcc %dst, 4, %g0 ! IEU1 Group (brz uses IEU1) be,pn %icc, ccdbl + 4 ! CTI -5: CSUMCOPY_ECACHE_LOAD( %o0, 0x00, %o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0x40,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0x80,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN_LDNXT(%o0,%o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STUNALIGN( %o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) +5: CSUMCOPY_ECACHE_LOAD( 0x00,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN_LDNXT(0x40,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN_LDNXT(0x80,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN_LDNXT(0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STUNALIGN( 0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) 10: - sub %g1, 256, %g1 ! IEU0 Group - add %o0, 256, %o0 ! IEU1 - andncc %g1, 0xff, %g0 ! IEU1 Group + sub %len, 256, %len ! IEU0 Group + add %src, 256, %src ! IEU1 + andncc %len, 0xff, %g0 ! IEU1 Group bne,pt %icc, 5b ! CTI - add %o1, 256, %o1 ! IEU0 -3: andcc %g1, 0xf0, %o2 ! IEU1 Group + add %dst, 256, %dst ! IEU0 +3: andcc %len, 0xf0, %g1 ! IEU1 Group ccmerge:be,pn %icc, ccte ! CTI - andcc %g1, 0xf, %o3 ! IEU1 Group - sll %o2, 2, %o4 ! IEU0 -13: rd %pc, %o5 ! LSU Group + 4 clocks - add %o0, %o2, %o0 ! IEU0 Group - sub %o5, %o4, %o5 ! IEU1 Group - jmpl %o5 + (12f - 13b), %g0 ! CTI Group brk forced - add %o1, %o2, %o1 ! IEU0 Group -cctbl: CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xe8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xd8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xc8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xb8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0xa8,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x98,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x88,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x78,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x58,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x48,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x38,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3) - CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3) + andcc %len, 0xf, %g7 ! IEU1 Group + sll %g1, 2, %o4 ! IEU0 +13: sethi %hi(12f), %o5 ! IEU0 Group + add %src, %g1, %src ! IEU1 + sub %o5, %o4, %o5 ! IEU0 Group + jmpl %o5 + %lo(12f), %g0 ! CTI Group brk forced + add %dst, %g1, %dst ! IEU0 Group +cctbl: CSUMCOPY_LASTCHUNK(0xe8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xd8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xc8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xb8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0xa8,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x98,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x88,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x78,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x68,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x58,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x48,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x38,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x28,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x18,%g2,%g3) + CSUMCOPY_LASTCHUNK(0x08,%g2,%g3) 12: - andcc %g1, 0xf, %o3 ! IEU1 Group + andcc %len, 0xf, %g7 ! IEU1 Group ccte: bne,pn %icc, cc_end_cruft ! CTI sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 -ccfold: sllx %g7, 32, %o0 ! IEU0 Group - addcc %g7, %o0, %o0 ! IEU1 Group (regdep) +ccfold: sllx %sum, 32, %o0 ! IEU0 Group + addcc %sum, %o0, %o0 ! IEU1 Group (regdep) srlx %o0, 32, %o0 ! IEU0 Group (regdep) 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 -ccdbl: CSUMCOPY_ECACHE_LOAD( %o0, 0x00, %o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0x40,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0x80,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED_LDNXT(%o0,%o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) - CSUMCOPY_EC_STALIGNED( %o1,0xc0,%g7,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) +ccdbl: CSUMCOPY_ECACHE_LOAD( 0x00,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED_LDNXT(0x40,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED_LDNXT(0x80,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED_LDNXT(0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) + CSUMCOPY_EC_STALIGNED( 0xc0,%o4,%o5,%g2,%g3,%g4,%g5,%g1,%g7) 11: - sub %g1, 256, %g1 ! IEU0 Group - add %o0, 256, %o0 ! IEU1 - andncc %g1, 0xff, %g0 ! IEU1 Group + sub %len, 256, %len ! IEU0 Group + add %src, 256, %src ! IEU1 + andncc %len, 0xff, %g0 ! IEU1 Group bne,pt %icc, ccdbl ! CTI - add %o1, 256, %o1 ! IEU0 + add %dst, 256, %dst ! IEU0 b,pt %xcc, ccmerge ! CTI Group - andcc %g1, 0xf0, %o2 ! IEU1 + andcc %len, 0xf0, %g1 ! IEU1 ccslow: mov 0, %g5 - brlez,pn %g1, 4f - andcc %o0, 1, %o5 + brlez,pn %len, 4f + andcc %src, 1, %o5 be,a,pt %icc, 1f - srl %g1, 1, %o3 - sub %g1, 1, %g1 - lduba [%o0] %asi, %g5 - add %o0, 1, %o0 - stb %g5, [%o1] - srl %g1, 1, %o3 - add %o1, 1, %o1 -1: brz,a,pn %o3, 3f - andcc %g1, 1, %g0 - andcc %o0, 2, %g0 + srl %len, 1, %g7 + sub %len, 1, %len + lduba [%src] %asi, %g5 + add %src, 1, %src + stb %g5, [%dst] + srl %len, 1, %g7 + add %dst, 1, %dst +1: brz,a,pn %g7, 3f + andcc %len, 1, %g0 + andcc %src, 2, %g0 be,a,pt %icc, 1f - srl %o3, 1, %o3 - lduha [%o0] %asi, %o4 - sub %g1, 2, %g1 + srl %g7, 1, %g7 + lduha [%src] %asi, %o4 + sub %len, 2, %len srl %o4, 8, %g2 - sub %o3, 1, %o3 - stb %g2, [%o1] + sub %g7, 1, %g7 + stb %g2, [%dst] add %o4, %g5, %g5 - stb %o4, [%o1 + 1] - add %o0, 2, %o0 - srl %o3, 1, %o3 - add %o1, 2, %o1 -1: brz,a,pn %o3, 2f - andcc %g1, 2, %g0 - lda [%o0] %asi, %o4 + stb %o4, [%dst + 1] + add %src, 2, %src + srl %g7, 1, %g7 + add %dst, 2, %dst +1: brz,a,pn %g7, 2f + andcc %len, 2, %g0 + lduwa [%src] %asi, %o4 5: srl %o4, 24, %g2 srl %o4, 16, %g3 - stb %g2, [%o1] + stb %g2, [%dst] srl %o4, 8, %g2 - stb %g3, [%o1 + 1] - add %o0, 4, %o0 - stb %g2, [%o1 + 2] + stb %g3, [%dst + 1] + add %src, 4, %src + stb %g2, [%dst + 2] addcc %o4, %g5, %g5 - stb %o4, [%o1 + 3] - addc %g5, %g0, %g5 ! I am now to lazy to optimize this (question is if it - add %o1, 4, %o1 ! is worthy). Maybe some day - with the sll/srl - subcc %o3, 1, %o3 ! tricks + stb %o4, [%dst + 3] + addc %g5, %g0, %g5 + add %dst, 4, %dst + subcc %g7, 1, %g7 bne,a,pt %icc, 5b - lda [%o0] %asi, %o4 + lduwa [%src] %asi, %o4 sll %g5, 16, %g2 srl %g5, 16, %g5 srl %g2, 16, %g2 - andcc %g1, 2, %g0 + andcc %len, 2, %g0 add %g2, %g5, %g5 2: be,a,pt %icc, 3f - andcc %g1, 1, %g0 - lduha [%o0] %asi, %o4 - andcc %g1, 1, %g0 + andcc %len, 1, %g0 + lduha [%src] %asi, %o4 + andcc %len, 1, %g0 srl %o4, 8, %g2 - add %o0, 2, %o0 - stb %g2, [%o1] + add %src, 2, %src + stb %g2, [%dst] add %g5, %o4, %g5 - stb %o4, [%o1 + 1] - add %o1, 2, %o1 + stb %o4, [%dst + 1] + add %dst, 2, %dst 3: be,a,pt %icc, 1f sll %g5, 16, %o4 - lduba [%o0] %asi, %g2 + lduba [%src] %asi, %g2 sll %g2, 8, %o4 - stb %g2, [%o1] + stb %g2, [%dst] add %g5, %o4, %g5 sll %g5, 16, %o4 1: addcc %o4, %g5, %g5 @@ -484,8 +484,22 @@ and %o4, 0xff, %o4 sll %g2, 8, %g2 or %g2, %o4, %g5 -4: addcc %g7, %g5, %g7 - addc %g0, %g7, %o0 +4: addcc %sum, %g5, %sum + addc %g0, %sum, %o0 retl srl %o0, 0, %o0 -__csum_partial_copy_end: +cpc_end: + + .globl cpc_handler +cpc_handler: + ldx [%sp + 0x7ff + 128], %g1 + sub %g0, EFAULT, %g2 + brnz,a,pt %g1, 1f + st %g2, [%g1] +1: retl + nop + + .section __ex_table + .align 8 + .xword cpc_start, 0, cpc_end, cpc_handler + diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/lib/locks.S linux/arch/sparc64/lib/locks.S --- v2.1.50/linux/arch/sparc64/lib/locks.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/lib/locks.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: locks.S,v 1.3 1997/07/22 05:51:42 davem Exp $ +/* $Id: locks.S,v 1.5 1997/07/31 05:28:16 davem Exp $ * locks.S: SMP low-level lock primitives on Sparc64. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -12,9 +12,9 @@ .align 32 ___lk_busy_spin: - orcc %g2, 0, %g0 - bne,pt %icc, ___lk_busy_spin - ldub [%g1 + 0], %g2 + ldub [%g1 + 0], %g2 + brnz,pt %g2, ___lk_busy_spin + membar #LoadLoad b,pt %xcc, 1f ldstub [%g1 + 0], %g2 @@ -23,16 +23,15 @@ addcc %g2, -1, %g2 rdpr %pil, %g3 bcs,a,pn %icc, 9f - st %g2, [%g6 + AOFF_task_lock_depth] + stw %g2, [%g6 + AOFF_task_lock_depth] wrpr %g0, 15, %pil ldstub [%g1 + 0], %g2 -1: brnz,a,pn %g2, ___lk_busy_spin - ldub [%g1 + 0], %g2 +1: brnz,pn %g2, ___lk_busy_spin + membar #StoreLoad | #StoreStore lduw [%g6 + AOFF_task_processor], %g2 - membar #LoadLoad | #LoadStore stb %g2, [%g1 + 1] 2: mov -1, %g2 - st %g2, [%g6 + AOFF_task_lock_depth] + stw %g2, [%g6 + AOFF_task_lock_depth] wrpr %g3, 0, %pil 9: jmpl %o7 + 0x8, %g0 mov %g5, %o7 @@ -41,16 +40,16 @@ ___lock_reacquire_kernel: rdpr %pil, %g3 wrpr %g0, 15, %pil - st %g2, [%g6 + AOFF_task_lock_depth] + stw %g2, [%g6 + AOFF_task_lock_depth] ldstub [%g1 + 0], %g2 1: brz,pt %g2, 3f - ldub [%g1 + 0], %g2 -2: brnz,a,pt %g2, 2b - ldub [%g1 + 0], %g2 + membar #StoreLoad | #StoreStore +2: ldub [%g1 + 0], %g2 + brnz,pt %g2, 2b + membar #LoadLoad b,pt %xcc, 1b ldstub [%g1 + 0], %g2 3: lduw [%g6 + AOFF_task_processor], %g2 - membar #LoadLoad | #LoadStore stb %g2, [%g1 + 1] wrpr %g3, 0, %pil jmpl %o7 + 0x8, %g0 diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.1.50/linux/arch/sparc64/mm/fault.c Thu Jul 17 10:06:04 1997 +++ linux/arch/sparc64/mm/fault.c Sat Aug 16 10:00:22 1997 @@ -217,56 +217,3 @@ out: unlock_kernel(); } - -void fixup_dcache_alias(struct vm_area_struct *vma, unsigned long address, pte_t pte) -{ - struct vm_area_struct *vmaring; - struct inode *inode; - unsigned long vaddr, offset, start; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int alias_found = 0; - - inode = vma->vm_dentry->d_inode; - if(!inode) - return; - - offset = (address & PAGE_MASK) - vma->vm_start; - vmaring = inode->i_mmap; - do { - vaddr = vmaring->vm_start + offset; - - /* This conditional is misleading... */ - if((vaddr ^ address) & PAGE_SIZE) { - alias_found++; - start = vmaring->vm_start; - while(start < vmaring->vm_end) { - pgdp = pgd_offset(vmaring->vm_mm, start); - if(!pgdp) goto next; - pmdp = pmd_offset(pgdp, start); - if(!pmdp) goto next; - ptep = pte_offset(pmdp, start); - if(!ptep) goto next; - - if(pte_val(*ptep) & _PAGE_PRESENT) { - flush_cache_page(vmaring, start); - *ptep = __pte(pte_val(*ptep) & - ~(_PAGE_CV)); - flush_tlb_page(vmaring, start); - } - next: - start += PAGE_SIZE; - } - } - } while((vmaring = vmaring->vm_next_share) != NULL); - - if(alias_found && (pte_val(pte) & _PAGE_CV)) { - pgdp = pgd_offset(vma->vm_mm, address); - pmdp = pmd_offset(pgdp, address); - ptep = pte_offset(pmdp, address); - flush_cache_page(vma, address); - *ptep = __pte(pte_val(*ptep) & ~(_PAGE_CV)); - flush_tlb_page(vma, address); - } -} diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.50/linux/arch/sparc64/mm/init.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/mm/init.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.40 1997/07/24 16:48:27 davem Exp $ +/* $Id: init.c,v 1.54 1997/08/15 06:44:23 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -37,6 +37,18 @@ /* References to section boundaries */ extern char __init_begin, __init_end, etext, __bss_start; +extern void __bfill64(void *, unsigned long *); + +static __inline__ void __init_pmd(pmd_t *pmdp) +{ + __bfill64((void *)pmdp, &null_pte_table); +} + +static __inline__ void __init_pgd(pgd_t *pgdp) +{ + __bfill64((void *)pgdp, &null_pmd_table); +} + /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -103,47 +115,71 @@ /* IOMMU support, the ideas are right, the code should be cleaned a bit still... */ -/* XXX Also, play with the streaming buffers at some point, both - * XXX Fusion and Sunfire both have them aparently... -DaveM - */ - /* This keeps track of pages used in sparc_alloc_dvma() invocations. */ static unsigned long dvma_map_pages[0x10000000 >> 16] = { 0, }; static unsigned long dvma_pages_current_offset = 0; static int dvma_pages_current_index = 0; +/* #define E3000_DEBUG */ + __initfunc(unsigned long iommu_init(int iommu_node, unsigned long memory_start, unsigned long memory_end, struct linux_sbus *sbus)) { struct iommu_struct *iommu; struct sysio_regs *sregs; - struct linux_prom_registers rprop[2]; + struct linux_prom64_registers rprop; unsigned long impl, vers; unsigned long control, tsbbase; unsigned long *iopte; + u32 rlow, rhigh; int err, i; - err = prom_getproperty(iommu_node, "reg", (char *)rprop, +#ifdef E3000_DEBUG + prom_printf("\niommu_init: [%x:%016lx:%016lx:%p] ", + iommu_node, memory_start, memory_end, sbus); +#endif + err = prom_getproperty(iommu_node, "reg", (char *)&rprop, sizeof(rprop)); if(err == -1) { prom_printf("iommu_init: Cannot map SYSIO control registers.\n"); prom_halt(); } - sregs = (struct sysio_regs *) sparc_alloc_io(rprop[0].phys_addr, - (void *)0, + rlow = (rprop.phys_addr & 0xffffffff); + rhigh = (rprop.phys_addr >> 32); +#ifdef E3000_DEBUG + prom_printf("rlow[%08x] rhigh[%08x] ", rlow, rhigh); +#endif + sregs = (struct sysio_regs *) sparc_alloc_io(rlow, (void *)0, sizeof(struct sysio_regs), - "SYSIO Regs", - rprop[0].which_io, 0x0); + "SYSIO Regs", rhigh, 0x0); +#ifdef E3000_DEBUG + prom_printf("sregs[%p]\n"); +#endif + if(!sregs) { + prom_printf("iommu_init: Fatal error, sysio regs not mapped\n"); + prom_halt(); + } memory_start = (memory_start + 7) & ~7; iommu = (struct iommu_struct *) memory_start; memory_start += sizeof(struct iommu_struct); + +#ifdef E3000_DEBUG + prom_printf("iommu_init: iommu[%p] ", iommu); +#endif + + spin_lock_init(&iommu->iommu_lock); iommu->sysio_regs = sregs; sbus->iommu = iommu; control = sregs->iommu_control; impl = (control & IOMMU_CTRL_IMPL) >> 60; vers = (control & IOMMU_CTRL_VERS) >> 56; +#ifdef E3000_DEBUG + prom_printf("sreg_control[%08x]\n", control); + prom_printf("IOMMU: IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n", + (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs); +#endif printk("IOMMU: IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n", (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs); @@ -168,7 +204,8 @@ /* Setup aliased mappings... */ for(i = 0; i < (65536 - 4096); i++) { - *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); + *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_STBUF | + IOPTE_CACHE | IOPTE_WRITE); *iopte |= (i << 16); iopte++; } @@ -177,15 +214,47 @@ for( ; i < 65536; i++) *iopte++ = 0; +#ifdef E3000_DEBUG + prom_printf("IOMMU: pte's mapped, enabling IOMMU... "); +#endif sregs->iommu_tsbbase = __pa(tsbbase); sregs->iommu_control = control; +#ifdef E3000_DEBUG + prom_printf("done\n"); +#endif + /* Get the streaming buffer going. */ + control = sregs->sbuf_control; + impl = (control & SYSIO_SBUFCTRL_IMPL) >> 60; + vers = (control & SYSIO_SBUFCTRL_REV) >> 56; +#ifdef E3000_DEBUG + prom_printf("IOMMU: enabling streaming buffer, control[%08x]... ", + control); +#endif + printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ", + (unsigned int)impl, (unsigned int)vers); + printk("FlushFLAG[%p,%016lx] ... ", + (iommu->sbuf_flushflag_va = (unsigned int *)memory_start), + (iommu->sbuf_flushflag_pa = __pa(memory_start))); + *(iommu->sbuf_flushflag_va) = 0; + memory_start += sizeof(unsigned long); /* yes, unsigned long, for alignment */ + + sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN); + +#ifdef E3000_DEBUG + prom_printf("done, returning %016lx\n", memory_start); +#endif + printk("ENABLED\n"); + + /* Finally enable DVMA arbitration for all devices, just in case. */ + sregs->sbus_control |= SYSIO_SBCNTRL_AEN; + return memory_start; } -void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr) +void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr, + struct linux_sbus *sbus) { - struct iommu_struct *iommu = SBus_chain->iommu; /* GROSS ME OUT! */ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; @@ -193,6 +262,7 @@ /* Find out if we need to grab some pages. */ if(!dvma_map_pages[dvma_pages_current_index] || ((dvma_pages_current_offset + len) > (1 << 16))) { + struct linux_sbus *sbus; unsigned long *iopte; unsigned long newpages = __get_free_pages(GFP_KERNEL, 3, 0); int i; @@ -212,9 +282,16 @@ /* Stick it in the IOMMU. */ i = (65536 - 4096) + i; - iopte = (unsigned long *)(iommu->page_table + i); - *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); - *iopte |= __pa(newpages); + for_each_sbus(sbus) { + struct iommu_struct *iommu = sbus->iommu; + unsigned long flags; + + spin_lock_irqsave(&iommu->iommu_lock, flags); + iopte = (unsigned long *)(iommu->page_table + i); + *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); + *iopte |= __pa(newpages); + spin_unlock_irqrestore(&iommu->iommu_lock, flags); + } } /* Get this out of the way. */ @@ -258,6 +335,33 @@ return (__u32)0; } +void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus) +{ + struct iommu_struct *iommu = sbus->iommu; + struct sysio_regs *sregs = iommu->sysio_regs; + unsigned long start = (unsigned long) vaddr; + unsigned long end = PAGE_ALIGN(start + len); + unsigned long flags; + unsigned int *sync_word; + + start &= PAGE_MASK; + + spin_lock_irqsave(&iommu->iommu_lock, flags); + + while(start < end) { + sregs->sbuf_pflush = start; + start += PAGE_SIZE; + } + sync_word = iommu->sbuf_flushflag_va; + sregs->sbuf_fsync = iommu->sbuf_flushflag_pa; + membar("#StoreLoad | #MemIssue"); + while((*sync_word & 0x1) == 0) + membar("#LoadLoad"); + *sync_word = 0; + + spin_unlock_irqrestore(&iommu->iommu_lock, flags); +} + void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) { while(sz >= 0) { @@ -273,6 +377,36 @@ } } +void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +{ + struct iommu_struct *iommu = sbus->iommu; + struct sysio_regs *sregs = iommu->sysio_regs; + unsigned long flags; + unsigned int *sync_word; + + spin_lock_irqsave(&iommu->iommu_lock, flags); + + while(sz >= 0) { + unsigned long start = sg[sz].dvma_addr; + unsigned long end = PAGE_ALIGN(start + sg[sz].len); + + start &= PAGE_MASK; + while(start < end) { + sregs->sbuf_pflush = start; + start += PAGE_SIZE; + } + sz--; + } + sync_word = iommu->sbuf_flushflag_va; + sregs->sbuf_fsync = iommu->sbuf_flushflag_pa; + membar("#StoreLoad | #MemIssue"); + while((*sync_word & 0x1) == 0) + membar("#LoadLoad"); + *sync_word = 0; + + spin_unlock_irqrestore(&iommu->iommu_lock, flags); +} + static char sfmmuinfo[512]; char *mmu_info(void) @@ -340,7 +474,7 @@ unsigned long prom_itlb_tag, prom_itlb_data; unsigned long prom_dtlb_tag, prom_dtlb_data; -static inline void inherit_locked_prom_mappings(void) +void inherit_locked_prom_mappings(int save_p) { int i; int dtlb_seen = 0; @@ -367,9 +501,12 @@ data = spitfire_get_dtlb_data(i); if(!dtlb_seen && (data & _PAGE_L)) { unsigned long tag = spitfire_get_dtlb_tag(i); - prom_dtlb_ent = i; - prom_dtlb_tag = tag; - prom_dtlb_data = data; + + if(save_p) { + prom_dtlb_ent = i; + prom_dtlb_tag = tag; + prom_dtlb_data = data; + } __asm__ __volatile__("stxa %%g0, [%0] %1" : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU)); membar("#Sync"); @@ -390,9 +527,12 @@ data = spitfire_get_itlb_data(i); if(!itlb_seen && (data & _PAGE_L)) { unsigned long tag = spitfire_get_itlb_tag(i); - prom_itlb_ent = i; - prom_itlb_tag = tag; - prom_itlb_data = data; + + if(save_p) { + prom_itlb_ent = i; + prom_itlb_tag = tag; + prom_itlb_data = data; + } __asm__ __volatile__("stxa %%g0, [%0] %1" : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU)); membar("#Sync"); @@ -443,10 +583,14 @@ /* If not locked, zap it. */ void __flush_tlb_all(void) { - unsigned long flags; + unsigned long pstate; int i; - save_flags(flags); cli(); + __asm__ __volatile__("rdpr %%pstate, %0\n\t" + "wrpr %0, %1, %%pstate\n\t" + "flushw" + : "=r" (pstate) + : "i" (PSTATE_IE)); for(i = 0; i < 64; i++) { if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) { __asm__ __volatile__("stxa %%g0, [%0] %1" @@ -465,19 +609,67 @@ membar("#Sync"); } } - restore_flags(flags); + __asm__ __volatile__("wrpr %0, 0, %%pstate" + : : "r" (pstate)); } -void get_new_mmu_context(struct mm_struct *mm, unsigned long ctx) +/* We are always protected by scheduler_lock under SMP. */ +void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx) { - if((ctx & ~(CTX_VERSION_MASK)) == 0) { - flush_tlb_all(); - ctx = (ctx & CTX_VERSION_MASK) + CTX_FIRST_VERSION; - if(ctx == 1) - ctx = CTX_FIRST_VERSION; + unsigned int new_ctx = *ctx; + + if((new_ctx & ~(CTX_VERSION_MASK)) == 0) { + new_ctx += CTX_FIRST_VERSION; + if(new_ctx == 1) + new_ctx = CTX_FIRST_VERSION; + *ctx = new_ctx; + DO_LOCAL_FLUSH(smp_processor_id()); + } + mm->context = new_ctx; + mm->cpu_vm_mask = 0; /* Callers sets it properly. */ + (*ctx)++; +} + +#ifndef __SMP__ +unsigned long *pgd_quicklist = NULL; +unsigned long *pmd_quicklist = NULL; +unsigned long *pte_quicklist = NULL; +unsigned long pgtable_cache_size = 0; +#endif + +pgd_t *get_pgd_slow(void) +{ + pgd_t *pgd; + + pgd = (pgd_t *) __get_free_page(GFP_KERNEL); + if(pgd) + __init_pgd(pgd); + return pgd; +} + +pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) +{ + pmd_t *pmd; + + pmd = (pmd_t *) __get_free_page(GFP_KERNEL); + if(pmd) { + __init_pmd(pmd); + pgd_set(pgd, pmd); + return pmd + offset; } - tlb_context_cache = ctx + 1; - mm->context = ctx; + return NULL; +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *) get_free_page(GFP_KERNEL); + if(pte) { + pmd_set(pmd, pte); + return pte + offset; + } + return NULL; } __initfunc(static void @@ -595,7 +787,7 @@ */ pt = phys_base | _PAGE_VALID | _PAGE_SZ4MB; pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W; - save_flags(flags); cli(); + __save_and_cli(flags); __asm__ __volatile__(" stxa %1, [%0] %3 stxa %2, [%5] %4 @@ -608,15 +800,18 @@ : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt), "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3) : "memory"); - restore_flags(flags); + __restore_flags(flags); /* Now set kernel pgd to upper alias so physical page computations * work. */ init_mm.pgd += ((shift) / (sizeof(pgd_t *))); - null_pmd_table = __pa(((unsigned long)&empty_null_pmd_table) + shift); - null_pte_table = __pa(((unsigned long)&empty_null_pte_table) + shift); + /* The funny offsets are to make page table operations much quicker and + * requite less state, see pgtable.h for gory details. + */ + null_pmd_table=__pa(((unsigned long)&empty_null_pmd_table)+shift); + null_pte_table=__pa(((unsigned long)&empty_null_pte_table)+shift); pmdp = (pmd_t *) &empty_null_pmd_table; for(i = 0; i < 1024; i++) @@ -658,7 +853,7 @@ flushi((long)&empty_zero_page); membar("#Sync"); - inherit_locked_prom_mappings(); + inherit_locked_prom_mappings(1); flush_tlb_all(); diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.1.50/linux/arch/sparc64/mm/ultra.S Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/mm/ultra.S Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.9 1997/07/24 12:15:08 davem Exp $ +/* $Id: ultra.S,v 1.18 1997/08/08 08:34:23 jj Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,28 +13,26 @@ .align 32 .globl __flush_tlb_mm, __flush_tlb_range, __flush_tlb_page __flush_tlb_mm: /* %o0 == (mm->context & 0x1fff) */ - rdpr %otherwin, %g1 - brz,pt %g1, 1f - mov %o7, %g3 - call __flushw_user - clr %g2 -1: rdpr %pil, %g1 -9: mov SECONDARY_CONTEXT, %g7 - wrpr %g0, 15, %pil - - ldxa [%g7] ASI_DMMU, %g2 + mov SECONDARY_CONTEXT, %g7 +9: ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 - be,pt %icc, 1f + bne,pn %icc, 1f mov 0x50, %g3 + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + retl + flush %g6 +1: rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate stxa %o0, [%g7] ASI_DMMU -1: stxa %g0, [%g3] ASI_DMMU_DEMAP - be,pt %icc, 1f - stxa %g0, [%g3] ASI_IMMU_DEMAP - + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + flush %g6 stxa %g2, [%g7] ASI_DMMU -1: wrpr %g1, 0x0, %pil + flush %g6 retl - flush %g6 + wrpr %g1, 0, %pstate + nop __flush_tlb_range: /* %o0 == (mm->context & 0x1fff), %o1 == start, %o2 == end */ sethi %hi(8192 - 1), %g5 or %g5, %lo(8192 - 1), %g5 @@ -43,19 +41,13 @@ sub %o2, %o1, %o3 add %g5, 1, %g5 - orcc %o1, 0x50, %o1 + orcc %o1, 0x10, %o1 srlx %o3, 13, %o4 - rdpr %otherwin, %g1 - brz,pt %g1, 1f - mov %o7, %g3 - call __flushw_user - - clr %g2 -1: cmp %o4, 96 + cmp %o4, 96 bgu,pn %icc, 9b - rdpr %pil, %g1 - mov SECONDARY_CONTEXT, %g7 - wrpr %g0, 15, %pil + mov SECONDARY_CONTEXT, %g7 + rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 @@ -66,37 +58,37 @@ stxa %g0, [%o1 + %o3] ASI_IMMU_DEMAP brnz,pt %o3, 1b sub %o3, %g5, %o3 - nop + flush %g6 - be,pt %icc, 1f - wrpr %g1, 0x0, %pil + be,a,pt %icc, 1f + nop stxa %g2, [%g7] ASI_DMMU -1: retl - flush %g6 +1: flush %g6 + wrpr %g1, 0, %pstate + retl + nop .align 32 __flush_tlb_page: /* %o0 == (mm->context & 0x1fff), %o1 == page & PAGE_MASK */ - rdpr %otherwin, %g1 - brz,pt %g1, 1f - mov %o7, %g3 - call __flushw_user - clr %g2 -1: rdpr %pil, %g1 mov SECONDARY_CONTEXT, %g7 - wrpr %g0, 15, %pil - ldxa [%g7] ASI_DMMU, %g2 cmp %g2, %o0 be,pt %icc, 1f or %o1, 0x10, %g3 + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + retl + flush %g6 +1: rdpr %pstate, %g1 + wrpr %g1, PSTATE_IE, %pstate stxa %o0, [%g7] ASI_DMMU -1: stxa %g0, [%g3] ASI_DMMU_DEMAP - be,pt %icc, 1f - stxa %g0, [%g3] ASI_IMMU_DEMAP + stxa %g0, [%g3] ASI_DMMU_DEMAP + stxa %g0, [%g3] ASI_IMMU_DEMAP + flush %g6 stxa %g2, [%g7] ASI_DMMU -1: wrpr %g1, 0x0, %pil + flush %g6 retl - flush %g6 + wrpr %g1, 0, %pstate #ifdef __SMP__ /* These are all called by the slaves of a cross call, at @@ -111,50 +103,29 @@ * %g2 scratch 1 * %g3 scratch 2 * %g4 scratch 3 - * - * NOTE: We do not acknowledge the UPA until we are done - * with the service. This is what tells the master - * that he can consider the effects of the flush - * "complete" on this cpu. */ .align 32 - .globl xcall_flush_tlb_page + .globl xcall_flush_tlb_page, xcall_flush_tlb_mm, xcall_flush_tlb_range xcall_flush_tlb_page: mov SECONDARY_CONTEXT, %g2 - nop + or %g6, 0x10, %g4 ldxa [%g2] ASI_DMMU, %g3 - cmp %g3, %g5 - be,pt %icc, 1f - or %g6, 0x10, %g4 stxa %g5, [%g2] ASI_DMMU -1: stxa %g0, [%g4] ASI_DMMU_DEMAP - - be,pt %icc, 1f - stxa %g0, [%g4] ASI_IMMU_DEMAP + stxa %g0, [%g4] ASI_DMMU_DEMAP + stxa %g0, [%g4] ASI_IMMU_DEMAP stxa %g3, [%g2] ASI_DMMU -1: b,pt %xcc, do_ivec_return - flush %g1 + retry - .align 32 - .globl xcall_flush_tlb_mm xcall_flush_tlb_mm: mov SECONDARY_CONTEXT, %g2 - nop + mov 0x50, %g4 ldxa [%g2] ASI_DMMU, %g3 - cmp %g3, %g5 - be,pt %icc, 1f - mov 0x50, %g4 stxa %g5, [%g2] ASI_DMMU -1: stxa %g0, [%g4] ASI_DMMU_DEMAP - - be,pt %icc, 1f - stxa %g0, [%g4] ASI_IMMU_DEMAP + stxa %g0, [%g4] ASI_DMMU_DEMAP + stxa %g0, [%g4] ASI_IMMU_DEMAP stxa %g3, [%g2] ASI_DMMU -1: b,pt %xcc, do_ivec_return - flush %g1 + retry - .align 32 - .globl xcall_flush_tlb_range xcall_flush_tlb_range: sethi %hi(8192 - 1), %g2 or %g2, %lo(8192 - 1), %g2 @@ -162,26 +133,54 @@ andn %g7, %g2, %g7 sub %g7, %g6, %g3 add %g2, 1, %g2 - orcc %g6, 0x50, %g6 + orcc %g6, 0x10, %g6 srlx %g3, 13, %g4 cmp %g4, 96 bgu,pn %icc, xcall_flush_tlb_mm mov SECONDARY_CONTEXT, %g4 ldxa [%g4] ASI_DMMU, %g7 - cmp %g7, %g5 - be,pt %icc, 1f - sub %g3, %g2, %g3 + sub %g3, %g2, %g3 stxa %g5, [%g4] ASI_DMMU + nop + nop 1: stxa %g0, [%g6 + %g3] ASI_DMMU_DEMAP stxa %g0, [%g6 + %g3] ASI_IMMU_DEMAP brnz,pt %g3, 1b sub %g3, %g2, %g3 - bne,a,pn %icc, 1f - stxa %g7, [%g4] ASI_DMMU -1: b,pt %xcc, do_ivec_return - flush %g1 + stxa %g7, [%g4] ASI_DMMU + retry + nop + nop + + .globl xcall_report_regs +xcall_report_regs: + rdpr %pstate, %g2 + wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + call __show_regs + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + b,pt %xcc, rtrap + clr %l6 + + .globl xcall_capture +xcall_capture: + rdpr %pstate, %g2 + wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + call smp_penguin_jailcell + nop + b,pt %xcc, rtrap + clr %l6 /* These two are not performance critical... */ .globl xcall_flush_tlb_all @@ -209,8 +208,8 @@ cmp %g2, 63 ble,pt %icc, 1b sll %g2, 3, %g3 - b,pt %xcc, do_ivec_return - flush %g1 + flush %g1 + retry .globl xcall_flush_cache_all xcall_flush_cache_all: @@ -222,6 +221,6 @@ cmp %g3, %g2 bleu,pt %xcc, 1b nop - b,pt %xcc, do_ivec_return - flush %g1 + flush %g1 + retry #endif /* __SMP__ */ diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c --- v2.1.50/linux/arch/sparc64/prom/p1275.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc64/prom/p1275.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: p1275.c,v 1.11 1997/07/24 12:15:11 davem Exp $ +/* $Id: p1275.c,v 1.12 1997/07/26 18:39:01 davem Exp $ * p1275.c: Sun IEEE 1275 PROM low level interface routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -64,7 +64,7 @@ long ctx = 0; p = p1275buf.prom_buffer; - save_and_cli(flags); + __save_and_cli(flags); ctx = spitfire_get_primary_context (); if (ctx) { flushw_user (); @@ -149,7 +149,7 @@ if (ctx) spitfire_set_primary_context (ctx); - restore_flags(flags); + __restore_flags(flags); return x; } diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/prom/ranges.c linux/arch/sparc64/prom/ranges.c --- v2.1.50/linux/arch/sparc64/prom/ranges.c Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/prom/ranges.c Sat Aug 16 09:51:09 1997 @@ -1,15 +1,21 @@ -/* $Id: ranges.c,v 1.3 1997/03/21 12:33:36 jj Exp $ +/* $Id: ranges.c,v 1.7 1997/08/15 06:44:29 davem Exp $ * ranges.c: Handle ranges in newer proms for obio/sbus. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#include #include #include #include #include +#include #include +#ifdef CONFIG_PCI +#include +#include +#endif struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; int num_obio_ranges; @@ -62,6 +68,35 @@ } } +/* Apply probed fhc ranges to registers passed, if no ranges return. */ +void prom_apply_fhc_ranges(struct linux_fhc *fhc, + struct linux_prom_registers *regs, + int nregs) +{ + if(fhc->num_fhc_ranges) + prom_adjust_regs(regs, nregs, fhc->fhc_ranges, + fhc->num_fhc_ranges); +} + +/* Apply probed central ranges to registers passed, if no ranges return. */ +void prom_apply_central_ranges(struct linux_central *central, + struct linux_prom_registers *regs, int nregs) +{ + if(central->num_central_ranges) + prom_adjust_regs(regs, nregs, central->central_ranges, + central->num_central_ranges); +} + +#ifdef CONFIG_PCI +void prom_apply_ebus_ranges(struct linux_ebus *ebus, + struct linux_prom_registers *regs, int nregs) +{ + if (ebus->num_ebus_ranges) + prom_adjust_regs(regs, nregs, ebus->ebus_ranges, + ebus->num_ebus_ranges); +} +#endif + __initfunc(void prom_ranges_init(void)) { } @@ -77,6 +112,74 @@ if (success != -1) sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges)); } + +__initfunc(void prom_central_ranges_init(int cnode, struct linux_central *central)) +{ + int success; + + central->num_central_ranges = 0; + success = prom_getproperty(central->prom_node, "ranges", + (char *) central->central_ranges, + sizeof (central->central_ranges)); + if (success != -1) + central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); +} + +__initfunc(void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc)) +{ + int success; + + fhc->num_fhc_ranges = 0; + success = prom_getproperty(fhc->prom_node, "ranges", + (char *) fhc->fhc_ranges, + sizeof (fhc->fhc_ranges)); + if (success != -1) + fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); +} + +#ifdef CONFIG_PCI +__initfunc(void prom_ebus_ranges_init(struct linux_ebus *ebus)) +{ + struct ebus_range { + unsigned int cld_space; + unsigned int cld_base; + unsigned int prn_space; + unsigned int prn_base_hi; + unsigned int prn_base_lo; + unsigned int size; + } ranges[PROMREG_MAX]; + int i, success; + + ebus->num_ebus_ranges = 0; + success = prom_getproperty(ebus->prom_node, "ranges", + (char *)ranges, sizeof (ranges)); + if (success != -1) + ebus->num_ebus_ranges = (success/sizeof(struct ebus_range)); + + for (i = 0; i < ebus->num_ebus_ranges; i++) { + ebus->ebus_ranges[i].ot_child_space = ranges[i].cld_space; + ebus->ebus_ranges[i].ot_child_base = ranges[i].cld_base; + ebus->ebus_ranges[i].ot_parent_space = + ranges[i].prn_space & 0x0f000000; + if (ranges[i].prn_base_hi) + prom_printf("WARNING: %s: ot_parent_base high lost\n"); + ebus->ebus_ranges[i].ot_parent_base = ranges[i].prn_base_lo; + ebus->ebus_ranges[i].or_size = ranges[i].size; + } +} + +__initfunc(void prom_pbm_ranges_init(int pnode, struct linux_pbm_info *pbm)) +{ + int success; + + pbm->num_pbm_ranges = 0; + success = prom_getproperty(pbm->prom_node, "ranges", + (char *)&pbm->pbm_ranges, + sizeof(pbm->pbm_ranges)); + if(success != -1) + pbm->num_pbm_ranges = (success/sizeof(struct linux_prom_pci_ranges)); +} +#endif void prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs) diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/prom/tree.c linux/arch/sparc64/prom/tree.c --- v2.1.50/linux/arch/sparc64/prom/tree.c Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/prom/tree.c Sat Aug 16 09:51:09 1997 @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.5 1997/03/24 17:44:01 jj Exp $ +/* $Id: tree.c,v 1.6 1997/08/12 16:32:48 davem Exp $ * tree.c: Basic device tree traversal/scanning for the Linux * prom library. * @@ -26,7 +26,7 @@ __inline__ int prom_getchild(int node) { - long cnode; + int cnode; if(node == -1) return 0; cnode = __prom_getchild(node); @@ -37,7 +37,7 @@ __inline__ int prom_getparent(int node) { - long cnode; + int cnode; if(node == -1) return 0; cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node); @@ -57,12 +57,12 @@ __inline__ int prom_getsibling(int node) { - long sibnode; + int sibnode; if(node == -1) return 0; sibnode = __prom_getsibling(node); if(sibnode == -1) return 0; - return (int)sibnode; + return sibnode; } /* Return the length in bytes of property 'prop' at node 'node'. diff -u --recursive --new-file v2.1.50/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.1.50/linux/arch/sparc64/vmlinux.lds Mon Jul 7 08:18:55 1997 +++ linux/arch/sparc64/vmlinux.lds Sat Aug 16 09:51:09 1997 @@ -52,11 +52,13 @@ . += 8192; empty_bad_pte_table = .; . += 8192; + empty_bad_page = .; + . += 8192; + . += 0x40; empty_null_pmd_table = .; . += 8192; + . += 0x40; empty_null_pte_table = .; - . += 8192; - empty_bad_page = .; . += 8192; } _end = . ; diff -u --recursive --new-file v2.1.50/linux/drivers/Makefile linux/drivers/Makefile --- v2.1.50/linux/drivers/Makefile Mon Aug 4 16:25:37 1997 +++ linux/drivers/Makefile Sat Aug 16 09:53:08 1997 @@ -9,7 +9,7 @@ SUB_DIRS := block char net misc #streams MOD_SUB_DIRS := $(SUB_DIRS) sbus -ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp +ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp macintosh ifdef CONFIG_PCI SUB_DIRS += pci @@ -17,6 +17,11 @@ ifdef CONFIG_SBUS SUB_DIRS += sbus +endif + +ifdef CONFIG_PPC +SUB_DIRS += macintosh +MOD_SUB_DIRS += macintosh endif # If CONFIG_SCSI is set, the core of scsi support will be added to the kernel, diff -u --recursive --new-file v2.1.50/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.1.50/linux/drivers/block/Makefile Sat May 24 09:10:23 1997 +++ linux/drivers/block/Makefile Sat Aug 16 09:53:08 1997 @@ -22,6 +22,10 @@ LX_OBJS := MX_OBJS := +ifeq ($(CONFIG_MAC_FLOPPY),y) +L_OBJS += swim3.o +endif + ifeq ($(CONFIG_BLK_DEV_FD),y) L_OBJS += floppy.o else diff -u --recursive --new-file v2.1.50/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.50/linux/drivers/block/floppy.c Sun Jun 29 10:51:09 1997 +++ linux/drivers/block/floppy.c Sat Aug 16 09:53:08 1997 @@ -3969,6 +3969,10 @@ } fdc_state[0].address = FDC1; + if (fdc_state[0].address == -1) { + unregister_blkdev(MAJOR_NR,"fd"); + return -ENODEV; + } #if N_FDC > 1 fdc_state[1].address = FDC2; #endif diff -u --recursive --new-file v2.1.50/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.1.50/linux/drivers/block/genhd.c Mon Aug 4 16:25:37 1997 +++ linux/drivers/block/genhd.c Sat Aug 16 09:53:08 1997 @@ -672,6 +672,132 @@ } #endif /* CONFIG_AMIGA_PARTITION */ +#ifdef CONFIG_MAC_PARTITION +#include + +/* + * Code to understand MacOS partition tables. + */ + +#define MAC_PARTITION_MAGIC 0x504d + +/* type field value for A/UX or other Unix partitions */ +#define APPLE_AUX_TYPE "Apple_UNIX_SVR2" + +struct mac_partition { + __u16 signature; /* expected to be MAC_PARTITION_MAGIC */ + __u16 res1; + __u32 map_count; /* # blocks in partition map */ + __u32 start_block; /* absolute starting block # of partition */ + __u32 block_count; /* number of blocks in partition */ + char name[32]; /* partition name */ + char type[32]; /* string type description */ + __u32 data_start; /* rel block # of first data block */ + __u32 data_count; /* number of data blocks */ + __u32 status; /* partition status bits */ + __u32 boot_start; + __u32 boot_size; + __u32 boot_load; + __u32 boot_load2; + __u32 boot_entry; + __u32 boot_entry2; + __u32 boot_cksum; + char processor[16]; /* identifies ISA of boot */ + /* there is more stuff after this that we don't need */ +}; + +#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ + +#define MAC_DRIVER_MAGIC 0x4552 + +/* Driver descriptor structure, in block 0 */ +struct mac_driver_desc { + __u16 signature; /* expected to be MAC_DRIVER_MAGIC */ + __u16 block_size; + __u32 block_count; + /* ... more stuff */ +}; + +static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec) +{ + struct buffer_head *bh; + int blk, blocks_in_map; + int dev_bsize, dev_pos, pos; + unsigned secsize; + int first_bootable = 1; + struct mac_partition *part; + struct mac_driver_desc *md; + + dev_bsize = get_ptable_blocksize(dev); + dev_pos = 0; + /* Get 0th block and look at the first partition map entry. */ + if ((bh = bread(dev, 0, dev_bsize)) == 0) { + printk("%s: error reading partition table\n", + kdevname(dev)); + return -1; + } + md = (struct mac_driver_desc *) bh->b_data; + if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { + brelse(bh); + return 0; + } + secsize = be16_to_cpu(md->block_size); + if (secsize >= dev_bsize) { + brelse(bh); + dev_pos = secsize; + if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) { + printk("%s: error reading partition table\n", + kdevname(dev)); + return -1; + } + } + part = (struct mac_partition *) (bh->b_data + secsize - dev_pos); + if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { + brelse(bh); + return 0; /* not a MacOS disk */ + } + blocks_in_map = be32_to_cpu(part->map_count); + for (blk = 1; blk <= blocks_in_map; ++blk) { + pos = blk * secsize; + if (pos >= dev_pos + dev_bsize) { + brelse(bh); + dev_pos = pos; + if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) { + printk("%s: error reading partition table\n", + kdevname(dev)); + return -1; + } + } + part = (struct mac_partition *) (bh->b_data + pos - dev_pos); + if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) + break; + blocks_in_map = be32_to_cpu(part->map_count); + add_partition(hd, current_minor, + fsec + be32_to_cpu(part->start_block) * (secsize/512), + be32_to_cpu(part->block_count) * (secsize/512)); + +#ifdef CONFIG_PMAC + /* + * If this is the first bootable partition, tell the + * setup code, in case it wants to make this the root. + */ + if (first_bootable + && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) + && strcasecmp(part->processor, "powerpc") == 0) { + note_bootable_part(dev, blk); + first_bootable = 0; + } +#endif /* CONFIG_PMAC */ + + ++current_minor; + } + brelse(bh); + printk("\n"); + return 1; +} + +#endif /* CONFIG_MAC_PARTITION */ + #ifdef CONFIG_ATARI_PARTITION #include @@ -846,6 +972,10 @@ #endif #ifdef CONFIG_ATARI_PARTITION if(atari_partition(hd, dev, first_sector)) + return; +#endif +#ifdef CONFIG_MAC_PARTITION + if (mac_partition(hd, dev, first_sector)) return; #endif printk(" unknown partition table\n"); diff -u --recursive --new-file v2.1.50/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.50/linux/drivers/block/ll_rw_blk.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/ll_rw_blk.c Sat Aug 16 09:53:08 1997 @@ -681,10 +681,13 @@ #ifdef CONFIG_BLK_DEV_EZ ez_init(); #endif +#ifdef CONFIG_MAC_FLOPPY + swim3_init(); +#endif #ifdef CONFIG_BLK_DEV_FD floppy_init(); #else -#if !defined (__mc68000__) +#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__) outb_p(0xc, 0x3f2); #endif #endif diff -u --recursive --new-file v2.1.50/linux/drivers/block/swim3.c linux/drivers/block/swim3.c --- v2.1.50/linux/drivers/block/swim3.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/swim3.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,1011 @@ +/* + * Driver for the SWIM3 (Super Woz Integrated Machine 3) + * floppy controller found on Power Macintoshes. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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 +#include +#include +#include + +#define MAJOR_NR FLOPPY_MAJOR +#include + +static int floppy_blocksizes[2] = {512}; +static int floppy_sizes[2] = {2880}; + +enum swim_state { + idle, + locating, + seeking, + settling, + do_transfer, + jogging, + available, + revalidating, + ejecting +}; + +#define REG(x) unsigned char x; char x ## _pad[15]; + +/* + * The names for these registers mostly represent speculation on my part. + * It will be interesting to see how close they are to the names Apple uses. + */ +struct swim3 { + REG(data); + REG(usecs); /* counts down at 1MHz */ + REG(error); + REG(mode); + REG(select); /* controls CA0, CA1, CA2 and LSTRB signals */ + REG(reg5); + REG(control); /* writing bits clears them */ + REG(status); /* writing bits sets them in control */ + REG(intr); + REG(nseek); /* # tracks to seek */ + REG(ctrack); /* current track number */ + REG(csect); /* current sector number */ + REG(ssize); /* sector size code?? */ + REG(sector); /* sector # to read or write */ + REG(nsect); /* # sectors to read or write */ + REG(intr_enable); +}; + +#define control_bic control +#define control_bis status + +/* Bits in select register */ +#define CA_MASK 7 +#define LSTRB 8 + +/* Bits in control register */ +#define DO_SEEK 0x80 +#define SELECT 0x20 +#define WRITE_SECTORS 0x10 +#define SCAN_TRACK 0x08 +#define DRIVE_ENABLE 0x02 +#define INTR_ENABLE 0x01 + +/* Bits in status register */ +#define DATA 0x08 + +/* Bits in intr and intr_enable registers */ +#define ERROR 0x20 +#define DATA_CHANGED 0x10 +#define TRANSFER_DONE 0x08 +#define SEEN_SECTOR 0x04 +#define SEEK_DONE 0x02 + +/* Select values for swim3_action */ +#define SEEK_POSITIVE 0 +#define SEEK_NEGATIVE 4 +#define STEP 1 +#define MOTOR_ON 2 +#define MOTOR_OFF 6 +#define EJECT 7 + +/* Select values for swim3_select and swim3_readbit */ +#define STEP_DIR 0 +#define STEPPING 1 +#define MOTOR_ON 2 +#define RELAX 3 +#define READ_DATA_0 4 +#define SINGLE_SIDED 6 +#define DRIVE_PRESENT 7 +#define DISK_IN 8 +#define WRITE_PROT 9 +#define TRACK_ZERO 10 +#define TACHO 11 +#define READ_DATA_1 12 +#define SEEK_COMPLETE 14 + +struct floppy_state { + enum swim_state state; + volatile struct swim3 *swim3; /* hardware registers */ + struct dbdma_regs *dma; /* DMA controller registers */ + int swim3_intr; /* interrupt number for SWIM3 */ + int dma_intr; /* interrupt number for DMA channel */ + int cur_cyl; /* cylinder head is on, or -1 */ + int cur_sector; /* last sector we saw go past */ + int req_cyl; /* the cylinder for the current r/w request */ + int head; /* head number ditto */ + int req_sector; /* sector number ditto */ + int scount; /* # sectors we're transferring at present */ + int retries; + int secpercyl; /* disk geometry information */ + int secpertrack; + int total_secs; + int write_prot; /* 1 if write-protected, 0 if not, -1 dunno */ + struct dbdma_cmd *dma_cmd; + int ref_count; + int expect_cyl; + struct timer_list timeout; + int ejected; + struct wait_queue *wait; + int wanted; + char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; +}; + +static struct floppy_state floppy_states[1]; + +static unsigned short write_preamble[] = { + 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, /* gap field */ + 0, 0, 0, 0, 0, 0, /* sync field */ + 0x99a1, 0x99a1, 0x99a1, 0x99fb, /* data address mark */ + 0x990f /* init CRC generator */ +}; + +static unsigned short write_postamble[] = { + 0x9904, /* insert CRC */ + 0x4e4e, 0x4e4e, + 0x9908, /* stop writing */ + 0, 0, 0, 0, 0, 0 +}; + +static void swim3_select(struct floppy_state *fs, int sel); +static void swim3_action(struct floppy_state *fs, int action); +static int swim3_readbit(struct floppy_state *fs, int bit); +static void do_fd_request(void); +static void start_request(struct floppy_state *fs); +static void scan_track(struct floppy_state *fs); +static void seek_track(struct floppy_state *fs, int n); +static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count); +static void setup_transfer(struct floppy_state *fs); +static void act(struct floppy_state *fs); +static void scan_timeout(unsigned long data); +static void seek_timeout(unsigned long data); +static void xfer_timeout(unsigned long data); +static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int grab_drive(struct floppy_state *fs, enum swim_state state, + int interruptible); +static void release_drive(struct floppy_state *fs); +static int fd_eject(struct floppy_state *fs); +static int floppy_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param); +static int floppy_open(struct inode *inode, struct file *filp); +static int floppy_release(struct inode *inode, struct file *filp); +static long floppy_read(struct inode *inode, struct file *filp, + char *buf, unsigned long count); +static long floppy_write(struct inode *inode, struct file *filp, + const char *buf, unsigned long count); +static int floppy_check_change(kdev_t dev); +static int floppy_revalidate(kdev_t dev); +int swim3_init(void); + +#define IOCTL_MODE_BIT 8 +#define OPEN_WRITE_BIT 16 + +static void swim3_select(struct floppy_state *fs, int sel) +{ + volatile struct swim3 *sw = fs->swim3; + + out_8(&sw->select, RELAX); + if (sel & 8) + out_8(&sw->control_bis, SELECT); + else + out_8(&sw->control_bic, SELECT); + out_8(&sw->select, sel & CA_MASK); +} + +static void swim3_action(struct floppy_state *fs, int action) +{ + volatile struct swim3 *sw = fs->swim3; + + swim3_select(fs, action); + udelay(1); + sw->select |= LSTRB; eieio(); + udelay(2); + sw->select &= ~LSTRB; eieio(); + udelay(1); + out_8(&sw->select, RELAX); +} + +static int swim3_readbit(struct floppy_state *fs, int bit) +{ + volatile struct swim3 *sw = fs->swim3; + int stat; + + swim3_select(fs, bit); + udelay(1); + stat = in_8(&sw->status); + out_8(&sw->select, RELAX); + return (stat & DATA) == 0; +} + +static void do_fd_request(void) +{ + start_request(&floppy_states[0]); + sti(); +} + +static void start_request(struct floppy_state *fs) +{ + int drive; + unsigned long x; + + if (fs->state == idle && fs->wanted) { + fs->state = available; + wake_up(&fs->wait); + return; + } + while (CURRENT && fs->state == idle) { + if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) + panic(DEVICE_NAME ": request list destroyed"); + if (CURRENT->bh && !buffer_locked(CURRENT->bh)) + panic(DEVICE_NAME ": block not locked"); +#if 0 + printk("do_fd_req: dev=%x cmd=%d sec=%ld nr_sec=%ld buf=%p\n", + kdev_t_to_nr(CURRENT->rq_dev), CURRENT->cmd, + CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer); + printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", + CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors); +#endif + + drive = MINOR(CURRENT->rq_dev); + if (drive != 0) { + end_request(0); + continue; + } + if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) { + end_request(0); + continue; + } + if (CURRENT->current_nr_sectors == 0) { + end_request(1); + continue; + } + if (fs->ejected) { + end_request(0); + continue; + } + + if (CURRENT->cmd == WRITE) { + if (fs->write_prot < 0) + fs->write_prot = swim3_readbit(fs, WRITE_PROT); + if (fs->write_prot) { + end_request(0); + continue; + } + } + + fs->req_cyl = CURRENT->sector / fs->secpercyl; + x = CURRENT->sector % fs->secpercyl; + fs->head = x / fs->secpertrack; + fs->req_sector = x % fs->secpertrack + 1; + fs->state = do_transfer; + fs->retries = 0; + + act(fs); + } +} + +static inline void scan_track(struct floppy_state *fs) +{ + volatile struct swim3 *sw = fs->swim3; + int xx; + + swim3_select(fs, READ_DATA_0); + xx = sw->intr; /* clear SEEN_SECTOR bit */ + out_8(&sw->control_bis, SCAN_TRACK); + /* enable intr when track found */ + out_8(&sw->intr_enable, ERROR | SEEN_SECTOR); + /* enable timeout */ + fs->timeout.expires = jiffies + HZ; + fs->timeout.function = scan_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); +} + +static inline void seek_track(struct floppy_state *fs, int n) +{ + volatile struct swim3 *sw = fs->swim3; + + if (n >= 0) { + swim3_action(fs, SEEK_POSITIVE); + sw->nseek = n; + } else { + swim3_action(fs, SEEK_NEGATIVE); + sw->nseek = -n; + } + fs->expect_cyl = (fs->cur_cyl > 0)? fs->cur_cyl + n: -1; + swim3_select(fs, STEP); + out_8(&sw->control_bis, DO_SEEK); + /* enable intr when seek finished */ + out_8(&sw->intr_enable, ERROR | SEEK_DONE); + /* enable timeout */ + fs->timeout.expires = jiffies + HZ/2; + fs->timeout.function = seek_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); +} + +static inline void init_dma(struct dbdma_cmd *cp, int cmd, + void *buf, int count) +{ + st_le16(&cp->req_count, count); + st_le16(&cp->command, cmd); + st_le32(&cp->phy_addr, virt_to_bus(buf)); + cp->xfer_status = 0; +} + +static inline void setup_transfer(struct floppy_state *fs) +{ + int n; + volatile struct swim3 *sw = fs->swim3; + struct dbdma_cmd *cp = fs->dma_cmd; + struct dbdma_regs *dr = fs->dma; + + if (CURRENT->current_nr_sectors <= 0) { + printk(KERN_ERR "swim3: transfer 0 sectors?\n"); + return; + } + if (CURRENT->cmd == WRITE) + n = 1; + else { + n = fs->secpertrack - fs->req_sector + 1; + if (n > CURRENT->current_nr_sectors) + n = CURRENT->current_nr_sectors; + } + fs->scount = n; + swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); + out_8(&sw->sector, fs->req_sector); + out_8(&sw->nsect, n); + out_8(&sw->ssize, 0); + st_le32(&dr->cmdptr, virt_to_bus(cp)); + if (CURRENT->cmd == WRITE) { + /* Set up 3 dma commands: write preamble, data, postamble */ + init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble)); + ++cp; + init_dma(cp, OUTPUT_MORE, CURRENT->buffer, 512); + ++cp; + init_dma(cp, OUTPUT_MORE, write_postamble, sizeof(write_postamble)); + } else { + init_dma(cp, INPUT_MORE, CURRENT->buffer, n * 512); + } + ++cp; + out_le16(&cp->command, DBDMA_STOP); + out_le32(&dr->control, (RUN << 16) | RUN); + out_8(&sw->control_bis, + (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK); + /* enable intr when transfer complete */ + out_8(&sw->intr_enable, ERROR | TRANSFER_DONE); + /* enable timeout */ + fs->timeout.expires = jiffies + 2*HZ; + fs->timeout.function = xfer_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); +} + +static void act(struct floppy_state *fs) +{ + volatile struct swim3 *sw = fs->swim3; + + for (;;) { + switch (fs->state) { + case idle: + return; /* XXX shouldn't get here */ + + case locating: + if (swim3_readbit(fs, TRACK_ZERO)) { + fs->cur_cyl = 0; + if (fs->req_cyl == 0) + fs->state = do_transfer; + else + fs->state = seeking; + break; + } + scan_track(fs); + return; + + case seeking: + if (fs->cur_cyl < 0) { + fs->expect_cyl = -1; + fs->state = locating; + break; + } + if (fs->req_cyl == fs->cur_cyl) { + printk("whoops, seeking 0\n"); + fs->state = do_transfer; + break; + } + seek_track(fs, fs->req_cyl - fs->cur_cyl); + return; + + case settling: + /* wait for SEEK_COMPLETE to become true */ + swim3_select(fs, SEEK_COMPLETE); + udelay(1); + out_8(&sw->intr_enable, ERROR | DATA_CHANGED); + in_8(&sw->intr); /* clear DATA_CHANGED */ + if (in_8(&sw->status) & DATA) { + /* seek_complete is not yet true */ + fs->timeout.expires = jiffies + HZ/2; + fs->timeout.function = seek_timeout; + fs->timeout.data = (unsigned long) fs; + add_timer(&fs->timeout); + return; + } + out_8(&sw->intr_enable, 0); + in_8(&sw->intr); + fs->state = locating; + break; + + case do_transfer: + if (fs->cur_cyl != fs->req_cyl) { + if (fs->retries > 5) { + end_request(0); + fs->state = idle; + return; + } + fs->state = seeking; + break; + } + setup_transfer(fs); + return; + + case jogging: + seek_track(fs, -5); + return; + + default: + printk(KERN_ERR"swim3: unknown state %d\n", fs->state); + return; + } + } +} + +static void scan_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + + out_8(&sw->control_bic, SCAN_TRACK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + fs->cur_cyl = -1; + if (fs->retries > 5) { + end_request(0); + fs->state = idle; + start_request(fs); + } else { + fs->state = jogging; + act(fs); + } +} + +static void seek_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + + if (fs->state == settling) { + printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n", + sw->select, sw->control, sw->status, sw->intr, sw->intr_enable); + } + out_8(&sw->control_bic, DO_SEEK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + if (fs->state == settling && swim3_readbit(fs, SEEK_COMPLETE)) { + /* printk(KERN_DEBUG "swim3: missed settling interrupt\n"); */ + fs->state = locating; + act(fs); + return; + } + printk(KERN_ERR "swim3: seek timeout\n"); + end_request(0); + fs->state = idle; + start_request(fs); +} + +static void xfer_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + struct dbdma_regs *dr = fs->dma; + struct dbdma_cmd *cp = fs->dma_cmd; + unsigned long s; + + st_le32(&dr->control, RUN << 16); + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); + out_8(&sw->select, RELAX); + if (CURRENT->cmd == WRITE) + ++cp; + if (ld_le16(&cp->xfer_status) != 0) + s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9); + else + s = 0; + CURRENT->sector += s; + CURRENT->current_nr_sectors -= s; + printk(KERN_ERR "swim3: timeout %sing sector %ld\n", + (CURRENT->cmd==WRITE? "writ": "read"), CURRENT->sector); + end_request(0); + fs->state = idle; + start_request(fs); +} + +static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct floppy_state *fs = (struct floppy_state *) dev_id; + volatile struct swim3 *sw = fs->swim3; + int intr, err, n; + int stat, resid; + struct dbdma_regs *dr; + struct dbdma_cmd *cp; + + err = in_8(&sw->error); + intr = in_8(&sw->intr); + if ((intr & ERROR) && fs->state != do_transfer) + printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n", + fs->state, CURRENT->cmd, intr, err); + switch (fs->state) { + case locating: + if (intr & SEEN_SECTOR) { + out_8(&sw->control_bic, SCAN_TRACK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + del_timer(&fs->timeout); + if (sw->ctrack == 0xff) { + printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); + fs->cur_cyl = -1; + if (fs->retries > 5) { + end_request(0); + fs->state = idle; + start_request(fs); + } else { + fs->state = jogging; + act(fs); + } + break; + } + fs->cur_cyl = sw->ctrack; + fs->cur_sector = sw->csect; + if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl) + printk(KERN_ERR "swim3: expected cyl %d, got %d\n", + fs->expect_cyl, fs->cur_cyl); + fs->state = do_transfer; + act(fs); + } + break; + case seeking: + case jogging: + if (sw->nseek == 0) { + out_8(&sw->control_bic, DO_SEEK); + out_8(&sw->select, RELAX); + out_8(&sw->intr_enable, 0); + del_timer(&fs->timeout); + if (fs->state == seeking) + ++fs->retries; + fs->state = settling; + act(fs); + } + break; + case settling: + out_8(&sw->intr_enable, 0); + del_timer(&fs->timeout); + act(fs); + break; + case do_transfer: + if ((intr & (ERROR | TRANSFER_DONE)) == 0) + break; + dr = fs->dma; + cp = fs->dma_cmd; + st_le32(&dr->control, RUN << 16); + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK); + out_8(&sw->select, RELAX); + del_timer(&fs->timeout); + if (CURRENT->cmd == WRITE) + ++cp; + stat = ld_le16(&cp->xfer_status); + resid = ld_le16(&cp->res_count); + if (intr & ERROR) { + n = fs->scount - 1 - resid / 512; + if (n > 0) { + CURRENT->sector += n; + CURRENT->current_nr_sectors -= n; + CURRENT->buffer += n * 512; + fs->req_sector += n; + } + if (fs->retries < 5) { + ++fs->retries; + act(fs); + } else { + printk("swim3: error %sing block %ld (err=%x)\n", + CURRENT->cmd == WRITE? "writ": "read", + CURRENT->sector, err); + end_request(0); + fs->state = idle; + } + } else { + if ((stat & ACTIVE) == 0 || resid != 0) { + /* musta been an error */ + printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid); + printk(KERN_ERR " state=%d, cmd=%x, intr=%x, err=%x\n", + fs->state, CURRENT->cmd, intr, err); + end_request(0); + fs->state = idle; + start_request(fs); + break; + } + CURRENT->sector += fs->scount; + CURRENT->current_nr_sectors -= fs->scount; + CURRENT->buffer += fs->scount * 512; + if (CURRENT->current_nr_sectors <= 0) { + end_request(1); + fs->state = idle; + } else { + fs->req_sector += fs->scount; + if (fs->req_sector > fs->secpertrack) { + fs->req_sector -= fs->secpertrack; + if (++fs->head > 1) { + fs->head = 0; + ++fs->req_cyl; + } + } + act(fs); + } + } + if (fs->state == idle) + start_request(fs); + break; + default: + printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state); + } +} + +static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +static int grab_drive(struct floppy_state *fs, enum swim_state state, + int interruptible) +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (fs->state != idle) { + ++fs->wanted; + while (fs->state != available) { + if (interruptible + && (current->signal & ~current->blocked)) { + --fs->wanted; + restore_flags(flags); + return -EINTR; + } + interruptible_sleep_on(&fs->wait); + } + --fs->wanted; + } + fs->state = state; + restore_flags(flags); + return 0; +} + +static void release_drive(struct floppy_state *fs) +{ + unsigned long flags; + + save_flags(flags); + cli(); + fs->state = idle; + start_request(fs); + restore_flags(flags); +} + +static int fd_eject(struct floppy_state *fs) +{ + int err, n; + + err = grab_drive(fs, ejecting, 1); + if (err) + return err; + swim3_action(fs, EJECT); + for (n = 2*HZ; n > 0; --n) { + if (swim3_readbit(fs, RELAX)) + break; + if ((current->signal & ~current->blocked) != 0) { + err = -EINTR; + break; + } + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + } + fs->ejected = 1; + release_drive(fs); + return err; +} + +static struct floppy_struct floppy_type = + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ + +static int floppy_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long param) +{ + struct floppy_state *fs; + int err; + + if (((cmd & 0x80) && !suser()) + || ((cmd & 0x40) && !(filp && (filp->f_mode & IOCTL_MODE_BIT)))) + return -EPERM; + + fs = &floppy_states[0]; + switch (cmd) { + case FDEJECT: + if (fs->ref_count != 1) + return -EBUSY; + err = fd_eject(fs); + return err; + case FDGETPRM: + err = copy_to_user((void *) param, (void *) &floppy_type, + sizeof(struct floppy_struct)); + return err; + } + return -ENOIOCTLCMD; +} + +static int floppy_open(struct inode *inode, struct file *filp) +{ + struct floppy_state *fs; + volatile struct swim3 *sw; + int n, err; + + if (MINOR(inode->i_rdev) != 0) + return -ENODEV; + fs = &floppy_states[0]; + sw = fs->swim3; + err = 0; + if (fs->ref_count == 0) { + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); + swim3_action(fs, MOTOR_ON); + fs->write_prot = -1; + fs->cur_cyl = -1; + for (n = HZ; n > 0; --n) { + if (swim3_readbit(fs, SEEK_COMPLETE)) + break; + if ((current->signal & ~current->blocked) != 0) { + err = -EINTR; + break; + } + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + } + if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0 + || swim3_readbit(fs, DISK_IN) == 0)) + err = -ENXIO; + swim3_action(fs, 9); + + } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL) + return -EBUSY; + + if (err == 0 && filp && (filp->f_flags & O_NDELAY) == 0 + && (filp->f_mode & 3)) { + check_disk_change(inode->i_rdev); + if (fs->ejected) + err = -ENXIO; + } + + if (err == 0 && filp && (filp->f_flags & (O_WRONLY | O_RDWR))) { + if (fs->write_prot < 0) + fs->write_prot = swim3_readbit(fs, WRITE_PROT); + if (fs->write_prot) + err = -EROFS; + } + + if (err) { + if (fs->ref_count == 0) { + swim3_action(fs, MOTOR_OFF); + out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE); + } + return err; + } + + if (filp->f_flags & O_EXCL) + fs->ref_count = -1; + else + ++fs->ref_count; + + /* Allow ioctls if we have write-permissions even if read-only open */ + if ((filp->f_mode & 2) || (permission(inode, 2) == 0)) + filp->f_mode |= IOCTL_MODE_BIT; + if (filp->f_mode & 2) + filp->f_mode |= OPEN_WRITE_BIT; + + return 0; +} + +static int floppy_release(struct inode *inode, struct file *filp) +{ + struct floppy_state *fs; + volatile struct swim3 *sw; + + if (MINOR(inode->i_rdev) != 0) + return -ENXIO; + fs = &floppy_states[0]; + if (filp == 0 || (filp->f_mode & (2 | OPEN_WRITE_BIT))) + block_fsync(inode, filp); + sw = fs->swim3; + if (fs->ref_count > 0 && --fs->ref_count == 0) { + swim3_action(fs, MOTOR_OFF); + out_8(&sw->control_bic, 0xff); + } + return 0; +} + +static int floppy_check_change(kdev_t dev) +{ + struct floppy_state *fs; + + if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0) + return 0; + fs = &floppy_states[0]; + return fs->ejected; +} + +static int floppy_revalidate(kdev_t dev) +{ + struct floppy_state *fs; + volatile struct swim3 *sw; + int ret, n; + + if (MAJOR(dev) != MAJOR_NR || MINOR(dev) != 0) + return 0; + fs = &floppy_states[0]; + sw = fs->swim3; + grab_drive(fs, revalidating, 0); + out_8(&sw->intr_enable, 0); + out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); + swim3_action(fs, MOTOR_ON); + fs->write_prot = -1; + fs->cur_cyl = -1; + for (n = HZ; n > 0; --n) { + if (swim3_readbit(fs, SEEK_COMPLETE)) + break; + if ((current->signal & ~current->blocked) != 0) + break; + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + } + ret = swim3_readbit(fs, SEEK_COMPLETE) == 0 + || swim3_readbit(fs, DISK_IN) == 0; + if (ret) + swim3_action(fs, MOTOR_OFF); + else { + fs->ejected = 0; + swim3_action(fs, 9); + } + + release_drive(fs); + return ret; +} + +static long floppy_read(struct inode *inode, struct file *filp, + char *buf, unsigned long count) +{ + struct floppy_state *fs; + + if (MINOR(inode->i_rdev) != 0) + return -ENODEV; + fs = &floppy_states[0]; + if (fs->ejected) + return -ENXIO; + return block_read(inode, filp, buf, count); +} + +static long floppy_write(struct inode *inode, struct file *filp, + const char *buf, unsigned long count) +{ + struct floppy_state *fs; + + if (MINOR(inode->i_rdev) != 0) + return -ENODEV; + fs = &floppy_states[0]; + if (fs->ejected) + return -ENXIO; + return block_write(inode, filp, buf, count); +} + +static void floppy_off(unsigned int nr) +{ +} + +static struct file_operations floppy_fops = { + NULL, /* lseek */ + floppy_read, /* read */ + floppy_write, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + floppy_ioctl, /* ioctl */ + NULL, /* mmap */ + floppy_open, /* open */ + floppy_release, /* release */ + block_fsync, /* fsync */ + NULL, /* fasync */ + floppy_check_change, /* check_media_change */ + floppy_revalidate, /* revalidate */ +}; + +int swim3_init(void) +{ + struct device_node *swims; + struct floppy_state *fs = &floppy_states[0]; + volatile struct swim3 *sw; + + swims = find_devices("swim3"); + if (swims == NULL) + return 0; + + if (swims->next != NULL) + printk(KERN_ERR "Warning: only using first SWIM3 floppy controller\n"); + if (swims->n_addrs != 2 || swims->n_intrs != 2) { + printk(KERN_ERR "swim3: expecting 2 addrs and 2 intrs! (%d, %d)\n", + swims->n_addrs, swims->n_intrs); + return -EINVAL; + } + + if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { + printk(KERN_ERR "Unable to get major %d for floppy\n", + MAJOR_NR); + return -EBUSY; + } + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + blksize_size[MAJOR_NR] = floppy_blocksizes; + blk_size[MAJOR_NR] = floppy_sizes; + + memset(fs, 0, sizeof(*fs)); + fs->state = idle; + fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address; + fs->dma = (struct dbdma_regs *) swims->addrs[1].address; + fs->swim3_intr = swims->intrs[0]; + fs->dma_intr = swims->intrs[1]; + fs->cur_cyl = -1; + fs->cur_sector = -1; + fs->secpercyl = 36; + fs->secpertrack = 18; + fs->total_secs = 2880; + + fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); + memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); + st_le16(&fs->dma_cmd[1].command, DBDMA_STOP); + + if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { + printk(KERN_ERR "Couldn't get irq %d for SWIM3\n", fs->swim3_intr); + return -EBUSY; + } + if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) { + printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA", + fs->dma_intr); + return -EBUSY; + } + + sw = fs->swim3; + out_8(&sw->mode, 0x95); + out_8(&sw->control_bic, 0xff); + out_8(&sw->reg5, 0x28); + + do_floppy = NULL; + + printk(KERN_INFO "fd0: SWIM3 floppy controller\n"); + + return 0; +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile --- v2.1.50/linux/drivers/macintosh/Makefile Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/Makefile Sat Aug 16 09:53:08 1997 @@ -0,0 +1,46 @@ +# +# Makefile for the Macintosh-specific device drivers. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now inherited from the +# parent makes.. +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) + +L_TARGET := macintosh.a +M_OBJS := +L_OBJS := via-cuda.o adb.o nvram.o + +ifeq ($(CONFIG_SERIAL),y) + LX_OBJS += macserial.o +else + ifeq ($(CONFIG_SERIAL),m) + MX_OBJS += macserial.o + endif +endif + +ifdef CONFIG_MAC_KEYBOARD +L_OBJS += mac_keyb.o mackeymap.o +endif + +ifdef CONFIG_VT + ifdef CONFIG_PMAC_CONSOLE + L_OBJS += pmac-cons.o control.o platinum.o valkyrie.o + ifdef CONFIG_ATY_VIDEO + L_OBJS += aty.o + endif + ifdef CONFIG_IMSTT_VIDEO + L_OBJS += imstt.o + endif + endif +endif + +include $(TOPDIR)/Rules.make + +mackeymap.c: mackeymap.map + loadkeys --mktable mackeymap.map > mackeymap.c diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c --- v2.1.50/linux/drivers/macintosh/adb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/adb.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,169 @@ +/* + * Device driver for the /dev/adb device on macintoshes. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADB_MAJOR 56 /* major number for /dev/adb */ + +extern void adbdev_init(void); + +struct adbdev_state { + struct cuda_request req; +}; + +static struct wait_queue *adb_wait; + +static int adb_wait_reply(struct adbdev_state *state, struct file *file) +{ + int ret = 0; + struct wait_queue wait = { current, NULL }; + + add_wait_queue(&adb_wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (!state->req.got_reply) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (current->signal & ~current->blocked) { + ret = -ERESTARTSYS; + break; + } + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&adb_wait, &wait); + + return ret; +} + +static void adb_write_done(struct cuda_request *req) +{ + if (!req->got_reply) { + req->reply_len = 0; + req->got_reply = 1; + } + wake_up_interruptible(&adb_wait); +} + +static int adb_open(struct inode *inode, struct file *file) +{ + struct adbdev_state *state; + + if (MINOR(inode->i_rdev) > 0) + return -ENXIO; + state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL); + if (state == 0) + return -ENOMEM; + file->private_data = state; + state->req.reply_expected = 0; + return 0; +} + +static int adb_release(struct inode *inode, struct file *file) +{ + struct adbdev_state *state = file->private_data; + + if (state) { + file->private_data = NULL; + if (state->req.reply_expected && !state->req.got_reply) + if (adb_wait_reply(state, file)) + return 0; + kfree(state); + } + return 0; +} + +static long long adb_lseek(struct inode *inode, struct file *file, + long long offset, int origin) +{ + return -ESPIPE; +} + +static long adb_read(struct inode *inode, struct file *file, + char *buf, unsigned long count) +{ + int ret; + struct adbdev_state *state = file->private_data; + + if (count < 2) + return -EINVAL; + if (count > sizeof(state->req.reply)) + count = sizeof(state->req.reply); + ret = verify_area(VERIFY_WRITE, buf, count); + if (ret) + return ret; + + if (!state->req.reply_expected) + return 0; + + ret = adb_wait_reply(state, file); + if (ret) + return ret; + + ret = state->req.reply_len; + copy_to_user(buf, state->req.reply, ret); + state->req.reply_expected = 0; + + return ret; +} + +static long adb_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) +{ + int ret; + struct adbdev_state *state = file->private_data; + + if (count < 2 || count > sizeof(state->req.data)) + return -EINVAL; + ret = verify_area(VERIFY_READ, buf, count); + if (ret) + return ret; + + if (state->req.reply_expected && !state->req.got_reply) { + /* A previous request is still being processed. + Wait for it to finish. */ + ret = adb_wait_reply(state, file); + if (ret) + return ret; + } + + state->req.nbytes = count; + state->req.done = adb_write_done; + copy_from_user(state->req.data, buf, count); + state->req.reply_expected = 1; + state->req.got_reply = 0; + cuda_send_request(&state->req); + + return count; +} + +static struct file_operations adb_fops = { + adb_lseek, + adb_read, + adb_write, + NULL, /* no readdir */ + NULL, /* no poll yet */ + NULL, /* no ioctl yet */ + NULL, /* no mmap */ + adb_open, + adb_release +}; + +void adbdev_init() +{ + if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) + printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/ati-gt.h linux/drivers/macintosh/ati-gt.h --- v2.1.50/linux/drivers/macintosh/ati-gt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/ati-gt.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,149 @@ +#if 0 /* not filled inaty_gt_reg_init yet */ +/* Register values for 1280x1024, 75Hz mode (20) */ +static struct aty_regvals aty_gt_reg_init_20 = { + { 0x10, 0x28, 0x3c }, + { }, + { } /* pixel clock = 134.61MHz for V=74.81Hz */ +}; + +/* Register values for 1280x960, 75Hz mode (19) */ +static struct aty_regvals aty_gt_reg_init_19 = { + { 0x10, 0x28, 0x3c }, + { }, + { } /* pixel clock = 126.01MHz for V=75.01 Hz */ +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_gt_reg_init_18 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 100.33MHz for V=75.31Hz */ +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_gt_reg_init_17 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 79.55MHz for V=74.50Hz */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_gt_reg_init_15 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 78.12MHz for V=72.12Hz */ +}; + +#endif + + +/* Register values for 1280x1024, 60Hz mode (20) */ +static struct aty_regvals aty_gt_reg_init_20 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20100000, + { 0x88, 0x7 } +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_gt_reg_init_17 = { + { 0, 0, 0 }, + + { 0xc0085, 0xc0083, 0xc0083 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a3, 0x2ff031f, 0x30300, 0x20100000, + { 0x41, 0x3 } +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_gt_reg_init_15 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20100000, + { 0x88, 0x7 } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_gt_reg_init_14 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3060200, 0x30d0300, 0x30d0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a7, 0x2ff0325, 0x260302, 0x20100000, + { 0x6c, 0x6 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_gt_reg_init_13 = { + { 0x200, 0x200, 0x200 }, + + { 0x28006f, 0x28006d, 0x28006c }, + { 0x3050200, 0x30b0300, 0x30e0600 }, + { 0x2002312, 0x3002312, 0x6002312 }, + + 0x67008f, 0x26f029a, 0x230270, 0x1a100040, + { 0x4f, 0x05 } +}; + +#if 0 /* not filled in yet */ +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_gt_reg_init_12 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_gt_reg_init_11 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_gt_reg_init_10 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct aty_regvals aty_gt_reg_init_7 = { + { 0x10, 0x30, 0x68 }, + { }, + { } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; +#endif + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_gt_reg_init_6 = { + { 0x200, 0x200, 0x200 }, + + { 0x28005b, 0x280059, 0x280058 }, + { 0x3040200, 0x3060300, 0x30c0600 }, + { 0x2002312, 0x3002312, 0x6002312 }, + + 0x4f006b, 0x1df020c, 0x2301e2, 0x14100040, + { 0x35, 0x07 } +}; + +#if 0 /* not filled in yet */ +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_gt_reg_init_5 = { + { 0x200, 0x200, 0x200 }, + { }, + { 0x35, 0x07 } +}; +#endif diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/ati-vt.h linux/drivers/macintosh/ati-vt.h --- v2.1.50/linux/drivers/macintosh/ati-vt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/ati-vt.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,147 @@ +#if 0 /* not filled inaty_vt_reg_init yet */ +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct aty_regvals aty_vt_reg_init_7 = { + { 0x10, 0x30, 0x68 }, + { }, + { } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_vt_reg_init_15 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 78.12MHz for V=72.12Hz */ +}; + +#endif + +/* Register values for 1280x1024, 60Hz mode (20) */ +static struct aty_regvals aty_vt_reg_init_20 = { + { 0, 0, 0 }, + { 0x2e02a7, 0x2e02a7, 0x2e02a7}, + { 0x3070200, 0x3070200, 0x3070200}, + { 0xa00cb22, 0xb00cb23, 0xe00cb24 }, + + 0x9f00d2, 0x3ff0429, 0x30400, 0x28000000, + { 0x00, 0xaa } +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_vt_reg_init_18 = { + { 0, 0, 0 }, + { 0x300295, 0x300194, 0x300194 }, + { 0x3060200, 0x30e0300, 0x30e0300 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x8f00b5, 0x3650392, 0x230368, 0x24000000, + { 0x00, 0x9d } + /* pixel clock = 100.33MHz for V=75.31Hz */ +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_vt_reg_init_17 = { + { 0, 0, 0 }, + + { 0x2c0283, 0x2c0182, 0x2c0182 }, + { 0x3060200, 0x30a0300, 0x30a0300 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x7f00a3, 0x2ff031f, 0x30300, 0x20000000, + { 0x01, 0xf7 } +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_vt_reg_init_15 = { + { 0, 0, 0 }, + + { 0x310284, 0x310183, 0x310183 }, + { 0x3060200, 0x3090300, 0x3090600 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20000000, + { 0x01, 0xeb } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_vt_reg_init_14 = { + { 0, 0, 0 }, + { 0x310284, 0x310183, 0x310183 }, + { 0x3060200, 0x3080300, 0x30f0600 }, + { 0xa00cb21, 0xb00cb22, 0xe00cb23 }, + + 0x7f00a7, 0x2ff0325, 0x260302, 0x20000000, + { 0x01, 0xcc } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_vt_reg_init_13 = { + { 0, 0, 0 }, + + { 0x28026d, 0x28016c, 0x28016c }, + { 0x3060200, 0x3080300, 0x30f0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x67008f, 0x26f029a, 0x230270, 0x1a000000, + { 0x01, 0xb4 } +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_vt_reg_init_12 = { + { 0, 0, 0 }, + { 0x2a0267, 0x2a0166, 0x2a0565 }, + { 0x3040200, 0x3060300, 0x30d0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x630083, 0x2570270, 0x30258, 0x19000000, + { 0x01, 0x9c } + /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_vt_reg_init_11 = { + { 0, 0, 0 }, + + { 0x2f026c, 0x2f016b, 0x2f056a }, + { 0x3040200, 0x3060300, 0x30d0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x630081, 0x257029b, 0x6027c, 0x19000000, + { 0x01, 0x9d } + /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_vt_reg_init_10 = { + { 0, 0, 0 }, + { 0x30026a, 0x300169, 0x300568 }, + { 0x3030200, 0x3050300, 0x30b0600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x630083, 0x2570273, 0x40258, 0x19000000, + { 0x02, 0xfb } +/* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_vt_reg_init_6 = { + { 0, 0, 0 }, + + { 0x280259, 0x280158, 0x280557 }, + { 0x3030200, 0x3040300, 0x3080600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x4f006b, 0x1df020c, 0x2301e2, 0x14000000, + { 0x02, 0xbe } +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_vt_reg_init_5 = { + { 0, 0, 0 }, + + { 0x2c0253, 0x2c0152, 0x2c0551 }, + { 0x3030200, 0x3040300, 0x3060600 }, + { 0xa00cb21, 0xb00cb21, 0xe00cb22 }, + + 0x4f0063, 0x1df020c, 0x2201e9, 0x14000000, + { 0x02, 0x9e } +}; diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/aty.c linux/drivers/macintosh/aty.c --- v2.1.50/linux/drivers/macintosh/aty.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/aty.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,568 @@ +/* + * aty.c: Console support for ATI/mach64 display adaptor cards. + * + * Copyright (C) 1997 Michael AK Tesch + * written with much help from Jon Howell + * changes to support the vt chip set by harry ac eaton + * + * 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 +#include +#include +#include +#include +#include +#include "pmac-cons.h" +#include "aty.h" + +struct aty_cmap_regs { + unsigned char windex; + unsigned char lut; + unsigned char mask; + unsigned char rindex; + unsigned char cntl; +}; + +struct aty_regvals { + int offset[3]; /* first pixel address */ + + int crtc_h_sync_strt_wid[3]; /* depth dependant */ + int crtc_gen_cntl[3]; + int mem_cntl[3]; + + int crtc_h_tot_disp; /* mode dependant */ + int crtc_v_tot_disp; + int crtc_v_sync_strt_wid; + int crtc_off_pitch; + + unsigned char clock_val[2]; /* vals for 20 and 21 */ +}; + +/*static void set_aty_clock(unsigned char *params);*/ +static int aty_vram_reqd(int vmode, int cmode); + +static unsigned char *frame_buffer; +static int total_vram; /* total amount of video memory, bytes */ +static int is_vt_chip; /* whether a vt chip type was detected */ + +static unsigned long aty_regbase; +static struct aty_cmap_regs *aty_cmap_regs; + +/* this array contains the number of bytes/line for each mode and color depth */ +static int pitch[20][3] = { + {0,0,0}, /* mode 1?? */ + {0,0,0}, /* mode 2?? */ + {0,0,0}, /* mode 3??*/ + {0,0,0}, /* mode 4?? */ + {640, 1280, 2560}, /* mode 5 */ + {640, 1280, 2560}, /* mode 6 */ + {640, 1280, 2560}, /* mode 7 */ + {800, 1600, 3200}, /* mode 8 */ + {0,0,0}, /* mode 9 ??*/ + {800, 1600, 3200}, /* mode 10 */ + {800, 1600, 3200}, /* mode 11 */ + {800, 1600, 3200}, /* mode 12 */ + {832, 1664, 3328}, /* mode 13 */ + {1024, 2048, 4096}, /* mode 14 */ + {1024, 2048, 4096}, /* mode 15 */ + {1024, 2048, 4096}, /* mode 16 */ + {1024, 2048, 4096}, /* mode 17 */ + {1152, 2304, 4608}, /* mode 18 */ + {1280, 2560, 5120}, /* mode 19 */ + {1280, 2560, 5120} /* mode 20 */ +}; + +#include "ati-gt.h" +#include "ati-vt.h" + +static struct aty_regvals *aty_gt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &aty_gt_reg_init_6, + &aty_gt_reg_init_6, + NULL, + NULL, NULL, + NULL, + NULL,NULL, + &aty_gt_reg_init_13, + &aty_gt_reg_init_14, + &aty_gt_reg_init_15, + NULL, + &aty_gt_reg_init_17, + NULL, + NULL, + &aty_gt_reg_init_20 +}; + +static struct aty_regvals *aty_vt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &aty_vt_reg_init_5, + &aty_vt_reg_init_6, + NULL, + NULL, NULL, + &aty_vt_reg_init_10, + &aty_vt_reg_init_11, + &aty_vt_reg_init_12, + &aty_vt_reg_init_13, + &aty_vt_reg_init_14, + &aty_vt_reg_init_15, + NULL, + &aty_vt_reg_init_17, + &aty_vt_reg_init_18, + NULL, + &aty_vt_reg_init_20 +}; + +static inline int aty_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * pitch[vmode-1][cmode]; +} + +extern inline unsigned aty_ld_rev(volatile unsigned long addr) +{ + unsigned val; + + (long)addr += (long)aty_regbase; + asm volatile("lwbrx %0,0,%1" : "=r" (val) : "r" (addr)); + return val; +} + +extern inline void aty_st_rev(volatile unsigned long addr, unsigned val) +{ + (long)addr += (long)aty_regbase; + asm volatile("stwbrx %0,0,%1" : : "r" (val), "r" (addr) : "memory"); +} + +extern inline unsigned char aty_ld_byte(volatile unsigned long addr) +{ + unsigned char val; + + val = *(char*)((long)addr+(long)aty_regbase); + return val; +} + +extern inline void aty_st_byte(volatile unsigned long addr, unsigned char val) +{ + *(unsigned char*)(addr+(unsigned long)aty_regbase) = val; +} + +void +aty_st_514( int offset, char val ) +{ + aty_WaitQueue(5); + aty_st_byte( DAC_CNTL, 1); + aty_st_byte( DAC_W_INDEX, offset & 0xff ); /* right addr byte */ + aty_st_byte( DAC_DATA, (offset>>8) & 0xff ); /* left addr byte */ + aty_st_byte( DAC_MASK, val ); + aty_st_byte( DAC_CNTL, 0 ); +} + +void +aty_st_pll( int offset, char val ) +{ + aty_WaitQueue(3); + aty_st_byte( CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN ); /* write addr byte */ + aty_st_byte( CLOCK_CNTL + 2, val); /* write the register value */ + aty_st_byte( CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN); +} + +#if 0 +unsigned char +aty_ld_514( int offset ) +{ +/* do the same thing as aty_st_514, just read the DAC_MASK instead of writing*/ +} +#endif + +void +aty_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i,scale; + + aty_WaitQueue(2); + aty_st_byte(DAC_CNTL, aty_ld_byte(DAC_CNTL) & 0xfc); + aty_st_byte(DAC_REGS + DAC_MASK, 0xff); + eieio(); + scale = (is_vt_chip) ? ((color_mode == CMODE_16) ? 3 : 0) : 0; + for (i = 0; i < ncolors; ++i) { + aty_WaitQueue(4); + aty_cmap_regs->windex = (index + i) << scale; eieio(); + aty_cmap_regs->lut = red[i]; eieio(); + aty_cmap_regs->lut = green[i]; eieio(); + aty_cmap_regs->lut = blue[i]; eieio(); + } + +} + +void +map_aty_display(struct device_node *dp) +{ + int i, sense; + unsigned long addr; + unsigned char bus, devfn; + unsigned short cmd; + + if (dp->next != 0) + printk("Warning: only using first ATI card detected\n"); + if (dp->n_addrs != 1) + panic("expecting 1 addresses for ATY (got %d)", dp->n_addrs); + + aty_regbase = (int)ioremap((0x7ffc00 + dp->addrs[0].address), 0x1000); + aty_cmap_regs = (struct aty_cmap_regs *)(aty_regbase+0xC0); + + /* enable memory-space accesses using config-space command register */ + if (pci_device_loc(dp, &bus, &devfn) == 0) { + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + if (cmd != 0xffff) { + cmd |= PCI_COMMAND_MEMORY; + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + } + } + + switch( aty_ld_rev(MEM_CNTL)&MEM_SIZE_ALIAS ) { + case MEM_SIZE_512K: + total_vram = 0x80000; + break; + case MEM_SIZE_1M: + total_vram = 0x100000; + break; + case MEM_SIZE_2M: + total_vram = 0x200000; + break; + case MEM_SIZE_4M: + total_vram = 0x400000; + break; + case MEM_SIZE_6M: + total_vram = 0x600000; + break; + case MEM_SIZE_8M: + total_vram = 0x800000; + break; + default: + total_vram = 0x80000; + } +#if 1 + printk("aty_display_init: node = %p, addrs = ", dp->node); + printk(" %x(%x)", dp->addrs[0].address, dp->addrs[0].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i]); + printk( "\nregbase: %x pci loc: %x:%x total_vram: %x cregs: %x\n", (int)aty_regbase, + bus, devfn, total_vram, (int)aty_cmap_regs ); +#endif + is_vt_chip = ((aty_ld_rev(CONFIG_CHIP_ID) & CFG_CHIP_TYPE) == MACH64_VT_ID); + /* Map in frame buffer */ + addr = dp->addrs[0].address; + + /* use the big-endian aperture (??) */ + addr += 0x800000; + frame_buffer = ioremap(addr, 0x800000); + + + /* sense = read_aty_sense(); XXX not yet, just give it mine */ + sense = 0x62b; + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || ((is_vt_chip) ? aty_vt_reg_init[video_mode-1] : aty_gt_reg_init[video_mode-1]) == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (((is_vt_chip) ? aty_vt_reg_init[video_mode-1] : aty_gt_reg_init[video_mode-1]) == 0) + video_mode = VMODE_640_480_60; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + while (aty_vram_reqd(video_mode, color_mode) > total_vram) { + while (color_mode > CMODE_8 + && aty_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + /* + * adjust the video mode smaller if there still is not enough VRAM + */ + if (aty_vram_reqd(video_mode, color_mode) > total_vram) + while ((((is_vt_chip) ? aty_vt_reg_init[--video_mode - 1] + : aty_gt_reg_init[--video_mode -1 ]) == 0) && (video_mode > VMODE_640_480_60)) ; + } +} + +#if 0 +static void +set_aty_clock(unsigned char *params) +{ + /* done in aty_init...probably need to change for different modes */ + printk("tried to set ATY clock\n"); +} +#endif + +void +RGB514_Program(int cmode) +{ + typedef struct { + char pixel_dly; + char misc2_cntl; + char pixel_rep; + char pixel_cntl_index; + char pixel_cntl_v1; + } RGB514_DAC_Table; + + static RGB514_DAC_Table RGB514DAC_Tab[8] = { + { 0, 0x41, 0x03, 0x71, 0x45 }, // 8bpp + { 0, 0x45, 0x04, 0x0c, 0x01 }, // 555 + { 0, 0x45, 0x06, 0x0e, 0x00 }, // XRGB + }; + RGB514_DAC_Table *pDacProgTab; + + pDacProgTab = &RGB514DAC_Tab[cmode]; + + aty_st_514(0x90, 0x00); + aty_st_514(0x04, pDacProgTab->pixel_dly); + aty_st_514(0x05, 0x00); + + aty_st_514(0x2, 0x1); + aty_st_514(0x71, pDacProgTab->misc2_cntl); + aty_st_514(0x0a, pDacProgTab->pixel_rep); + + aty_st_514(pDacProgTab->pixel_cntl_index, pDacProgTab->pixel_cntl_v1); +} + +/* The vt chipset seems to need a specialized color table for 15 bit mode */ +void +VT_Program(int cmode) +{ +#if 0 + int i; + if (cmode != CMODE_8) { + aty_WaitQueue(2); + aty_cmap_regs->mask = 0xff; eieio(); + aty_cmap_regs->windex = 0; eieio(); + for (i = 0; i < 0x100; i++) { + aty_WaitQueue(3); + aty_cmap_regs->lut = i; + aty_cmap_regs->lut = i; + aty_cmap_regs->lut = i; eieio(); + } + } +#endif +} + +void +aty_init() +{ + int i, yoff, hres; + unsigned *p; + struct aty_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = ((is_vt_chip) ? aty_vt_reg_init[video_mode-1] : aty_gt_reg_init[video_mode-1])) == 0) + panic("aty: display mode %d not supported", video_mode); + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = pitch[video_mode-1][color_mode]; + row_pitch = line_pitch * 16; + + aty_st_rev(BUS_CNTL, aty_ld_rev(BUS_CNTL) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK); + + /* Reset engine */ + i = aty_ld_rev(GEN_TEST_CNTL); + aty_st_rev(GEN_TEST_CNTL, i & ~GUI_ENGINE_ENABLE); + eieio(); + aty_WaitIdleEmpty(); + aty_st_rev(GEN_TEST_CNTL, i | GUI_ENGINE_ENABLE); + aty_WaitIdleEmpty(); + + i = aty_ld_byte(CRTC_GEN_CNTL+3); + aty_st_byte(CRTC_GEN_CNTL+3, i | (CRTC_EXT_DISP_EN >> 24)); + + i = aty_ld_byte(GEN_TEST_CNTL); + aty_st_byte(GEN_TEST_CNTL, i | GEN_OVR_OUTPUT_EN ); + + if (!is_vt_chip) { + RGB514_Program(color_mode); + + aty_WaitIdleEmpty(); + + aty_st_514(0x06, 0x02); + aty_st_514(0x10, 0x01); + aty_st_514(0x70, 0x01); + aty_st_514(0x8f, 0x1f); + aty_st_514(0x03, 0x00); + aty_st_514(0x05, 0x00); + + aty_st_514(0x20, init->clock_val[0]); + aty_st_514(0x21, init->clock_val[1]); + } else { + VT_Program(color_mode); + aty_st_pll(PLL_MACRO_CNTL, 0xb5); + aty_st_pll(PLL_REF_DIV, 0x2d); + aty_st_pll(PLL_GEN_CNTL, 0x14); + aty_st_pll(MCLK_FB_DIV, 0xbd); + aty_st_pll(PLL_VCLK_CNTL, 0x0b); + aty_st_pll(VCLK_POST_DIV, init->clock_val[0]); + aty_st_pll(VCLK0_FB_DIV, init->clock_val[1]); + aty_st_pll(VCLK1_FB_DIV, 0xd6); + aty_st_pll(VCLK2_FB_DIV, 0xee); + aty_st_pll(VCLK3_FB_DIV, 0xf8); + aty_st_pll(PLL_XCLK_CNTL, 0x0); + aty_st_pll(PLL_TEST_CTRL, 0x0); + aty_st_pll(PLL_TEST_COUNT, 0x0); + } + + aty_ld_byte( DAC_REGS ); /* clear counter */ + + aty_WaitIdleEmpty(); + + aty_st_rev(CRTC_H_TOTAL_DISP, init->crtc_h_tot_disp); + aty_st_rev(CRTC_H_SYNC_STRT_WID, init->crtc_h_sync_strt_wid[color_mode]); + aty_st_rev(CRTC_V_TOTAL_DISP, init->crtc_v_tot_disp); + aty_st_rev(CRTC_V_SYNC_STRT_WID, init->crtc_v_sync_strt_wid); + + aty_st_byte(CLOCK_CNTL, 0); + aty_st_byte(CLOCK_CNTL, CLOCK_STROBE); + + aty_st_rev(CRTC_OFF_PITCH, init->crtc_off_pitch); + + aty_st_rev(CRTC_VLINE_CRNT_VLINE, 0x14e01d0); +/* The magic constant below translates into: + * 5 = No RDY delay, 1 wait st for mem write, increment during burst transfer + * 9 = DAC access delayed, 1 wait state for DAC + * 0 = Disables interupts for FIFO errors + * e = Allows FIFO to generate 14 wait states before generating error + * 1 = DAC snooping disabled, ROM disabled + * 0 = ROM page at 0 (disabled so doesn't matter) + * f = 15 ROM wait states (disabled so doesn't matter) + * f = 15 BUS wait states (I'm not sure this applies to PCI bus types) + * at some point it would be good to experiment with bench marks to see if + * we can gain some speed by fooling with the wait states etc. + */ + aty_st_rev(BUS_CNTL, 0x590e10ff); + i = aty_ld_rev(MEM_CNTL) & MEM_SIZE_ALIAS; + if (total_vram >= 0x400000) + aty_st_rev(MEM_CNTL, (init->mem_cntl[color_mode] &0xffff0000) | 0x0538 | i); + else + aty_st_rev(MEM_CNTL, (init->mem_cntl[color_mode] & ~MEM_SIZE_ALIAS) | i ); + aty_st_rev(CRTC_INT_CNTL, 0x2); + aty_WaitIdleEmpty(); +/* These magic constants are harder to figure out + * on the vt chipset bit 3 set makes the screen brighter + * and bit 15 makes the screen black! But nothing else + * seems to matter for the vt DAC_CNTL + */ + if (is_vt_chip) + aty_st_rev(DAC_CNTL, 0x47012104); + else + aty_st_rev(DAC_CNTL, 0x47012100); + + aty_st_byte(DAC_MASK, 0xff); + + aty_st_rev(CRTC_INT_CNTL, 0x00000002); + + aty_st_byte(CRTC_FIFO, ((char*)&init->crtc_gen_cntl[color_mode])[1] ); + aty_st_byte(CRTC_PIX_WIDTH, ((char*)&init->crtc_gen_cntl[color_mode])[2] ); + aty_st_byte(CRTC_EXT_DISP, ((char*)&init->crtc_gen_cntl[color_mode])[0] ); + + aty_st_rev(GEN_TEST_CNTL, 0x300); /* gui_en block_en*/ + + pmac_init_palette(); /* Initialize colormap */ + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + init->offset[color_mode]; + + /* Clear screen */ + p = (unsigned *) fb_start; + + for (i = n_scanlines * line_pitch * pixel_size / sizeof(unsigned); i != 0; --i) + *p++ = 0; + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "ATY Mach64", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + init->offset[color_mode]; + display_info.cmap_adr_address = (unsigned long) &aty_cmap_regs->windex; + display_info.cmap_data_address = (unsigned long) &aty_cmap_regs->lut; + display_info.disp_reg_address = aty_regbase; +} + +int +aty_setmode(struct vc_mode *mode, int doit) +{ + int cmode; +#if 0 + if (mode->mode == 21) { + printk("hace: about to set 0x%x to 0x%x\n",mode->depth, mode->pitch & 0xff); + aty_st_byte(mode->depth, mode->pitch & 0xff); + return 0; + } + + if (mode->mode == 0) { + printk("hace: 0x%x contains 0x%x\n",mode->depth, aty_ld_byte(mode->depth)); + return 0; + } +#endif + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || ((is_vt_chip) ? aty_vt_reg_init[mode->mode-1] : aty_gt_reg_init[mode->mode-1]) == NULL) + return -EINVAL; + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (aty_vram_reqd(mode->mode, cmode) > total_vram) { + return -EINVAL; + } + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + aty_init(); + } + return 0; +} + +void +aty_set_blanking(int blank_mode) +{ + char gen_cntl; + + gen_cntl = aty_ld_byte(CRTC_GEN_CNTL); + if (blank_mode & VESA_VSYNC_SUSPEND) + gen_cntl |= 0x8; + if (blank_mode & VESA_HSYNC_SUSPEND) + gen_cntl |= 0x4; + if ((blank_mode & VESA_POWERDOWN) == VESA_POWERDOWN) + gen_cntl |= 0x40; + if (blank_mode == VESA_NO_BLANKING) + gen_cntl &= ~(0x4c); + aty_st_byte(CRTC_GEN_CNTL, gen_cntl); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/aty.h linux/drivers/macintosh/aty.h --- v2.1.50/linux/drivers/macintosh/aty.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/aty.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,614 @@ +/* + * Exported procedures for the ATI/mach64 display driver on PowerMacs. + * + * Copyright (C) 1997 Michael AK Tesch + * written with much help from Jon Howell + * + * 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. + */ + +extern void map_aty_display(struct device_node *); +extern void aty_init(void); +extern int aty_setmode(struct vc_mode *mode, int doit); +extern void aty_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void aty_set_blanking(int blank_mode); + +/* + * most of the rest of this file comes from ATI sample code + */ +#ifndef REGMACH64_H +#define REGMACH64_H + +/* NON-GUI MEMORY MAPPED Registers - expressed in BYTE offsets */ + +#define CRTC_H_TOTAL_DISP 0x0000 /* Dword offset 00 */ +#define CRTC_H_SYNC_STRT_WID 0x0004 /* Dword offset 01 */ +#define CRTC_H_SYNC_STRT 0x0004 +#define CRTC_H_SYNC_DLY 0x0005 +#define CRTC_H_SYNC_WID 0x0006 + +#define CRTC_V_TOTAL_DISP 0x0008 /* Dword offset 02 */ +#define CRTC_V_TOTAL 0x0008 +#define CRTC_V_DISP 0x000a +#define CRTC_V_SYNC_STRT_WID 0x000C /* Dword offset 03 */ +#define CRTC_V_SYNC_STRT 0x000c +#define CRTC_V_SYNC_WID 0x000e + +#define CRTC_VLINE_CRNT_VLINE 0x0010 /* Dword offset 04 */ +#define CRTC_OFF_PITCH 0x0014 /* Dword offset 05 */ +#define CRTC_OFFSET 0x0014 +#define CRTC_PITCH 0x0016 + +#define CRTC_INT_CNTL 0x0018 /* Dword offset 06 */ +#define CRTC_GEN_CNTL 0x001C /* Dword offset 07 */ +#define CRTC_PIX_WIDTH 0x001d +#define CRTC_FIFO 0x001e +#define CRTC_EXT_DISP 0x001f + +#define OVR_CLR 0x0040 /* Dword offset 10 */ +#define OVR_WID_LEFT_RIGHT 0x0044 /* Dword offset 11 */ +#define OVR_WID_TOP_BOTTOM 0x0048 /* Dword offset 12 */ + +#define CUR_CLR0 0x0060 /* Dword offset 18 */ +#define CUR_CLR1 0x0064 /* Dword offset 19 */ +#define CUR_OFFSET 0x0068 /* Dword offset 1A */ +#define CUR_HORZ_VERT_POSN 0x006C /* Dword offset 1B */ +#define CUR_HORZ_VERT_OFF 0x0070 /* Dword offset 1C */ + +#define SCRATCH_REG0 0x0080 /* Dword offset 20 */ +#define SCRATCH_REG1 0x0084 /* Dword offset 21 */ + +#define CLOCK_CNTL 0x0090 /* Dword offset 24 */ +#define CLOCK_SEL_CNTL 0x0090 // Dword offset 24 + +#define BUS_CNTL 0x00A0 /* Dword offset 28 */ + +#define MEM_CNTL 0x00B0 /* Dword offset 2C */ + +#define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 2D */ +#define MEM_VGA_RP_SEL 0x00B8 /* Dword offset 2E */ + +#define DAC_REGS 0x00C0 /* Dword offset 30 */ +#define DAC_W_INDEX 0x00C0 /* Dword offset 30 */ +#define DAC_DATA 0x00C1 /* Dword offset 30 */ +#define DAC_MASK 0x00C2 /* Dword offset 30 */ +#define DAC_R_INDEX 0x00C3 /* Dword offset 30 */ +#define DAC_CNTL 0x00C4 /* Dword offset 31 */ + +#define GEN_TEST_CNTL 0x00D0 /* Dword offset 34 */ + +#define CONFIG_CNTL 0x00DC /* Dword offset 37 (CT, ET, VT) */ +#define CONFIG_CHIP_ID 0x00E0 /* Dword offset 38 */ +#define CONFIG_STAT0 0x00E4 /* Dword offset 39 */ +#define CONFIG_STAT1 0x00E8 /* Dword offset 3A */ + + +/* GUI MEMORY MAPPED Registers */ + +#define DST_OFF_PITCH 0x0100 /* Dword offset 40 */ +#define DST_X 0x0104 /* Dword offset 41 */ +#define DST_Y 0x0108 /* Dword offset 42 */ +#define DST_Y_X 0x010C /* Dword offset 43 */ +#define DST_WIDTH 0x0110 /* Dword offset 44 */ +#define DST_HEIGHT 0x0114 /* Dword offset 45 */ +#define DST_HEIGHT_WIDTH 0x0118 /* Dword offset 46 */ +#define DST_X_WIDTH 0x011C /* Dword offset 47 */ +#define DST_BRES_LNTH 0x0120 /* Dword offset 48 */ +#define DST_BRES_ERR 0x0124 /* Dword offset 49 */ +#define DST_BRES_INC 0x0128 /* Dword offset 4A */ +#define DST_BRES_DEC 0x012C /* Dword offset 4B */ +#define DST_CNTL 0x0130 /* Dword offset 4C */ + +#define SRC_OFF_PITCH 0x0180 /* Dword offset 60 */ +#define SRC_X 0x0184 /* Dword offset 61 */ +#define SRC_Y 0x0188 /* Dword offset 62 */ +#define SRC_Y_X 0x018C /* Dword offset 63 */ +#define SRC_WIDTH1 0x0190 /* Dword offset 64 */ +#define SRC_HEIGHT1 0x0194 /* Dword offset 65 */ +#define SRC_HEIGHT1_WIDTH1 0x0198 /* Dword offset 66 */ +#define SRC_X_START 0x019C /* Dword offset 67 */ +#define SRC_Y_START 0x01A0 /* Dword offset 68 */ +#define SRC_Y_X_START 0x01A4 /* Dword offset 69 */ +#define SRC_WIDTH2 0x01A8 /* Dword offset 6A */ +#define SRC_HEIGHT2 0x01AC /* Dword offset 6B */ +#define SRC_HEIGHT2_WIDTH2 0x01B0 /* Dword offset 6C */ +#define SRC_CNTL 0x01B4 /* Dword offset 6D */ + +#define HOST_DATA0 0x0200 /* Dword offset 80 */ +#define HOST_DATA1 0x0204 /* Dword offset 81 */ +#define HOST_DATA2 0x0208 /* Dword offset 82 */ +#define HOST_DATA3 0x020C /* Dword offset 83 */ +#define HOST_DATA4 0x0210 /* Dword offset 84 */ +#define HOST_DATA5 0x0214 /* Dword offset 85 */ +#define HOST_DATA6 0x0218 /* Dword offset 86 */ +#define HOST_DATA7 0x021C /* Dword offset 87 */ +#define HOST_DATA8 0x0220 /* Dword offset 88 */ +#define HOST_DATA9 0x0224 /* Dword offset 89 */ +#define HOST_DATAA 0x0228 /* Dword offset 8A */ +#define HOST_DATAB 0x022C /* Dword offset 8B */ +#define HOST_DATAC 0x0230 /* Dword offset 8C */ +#define HOST_DATAD 0x0234 /* Dword offset 8D */ +#define HOST_DATAE 0x0238 /* Dword offset 8E */ +#define HOST_DATAF 0x023C /* Dword offset 8F */ +#define HOST_CNTL 0x0240 /* Dword offset 90 */ + +#define PAT_REG0 0x0280 /* Dword offset A0 */ +#define PAT_REG1 0x0284 /* Dword offset A1 */ +#define PAT_CNTL 0x0288 /* Dword offset A2 */ + +#define SC_LEFT 0x02A0 /* Dword offset A8 */ +#define SC_RIGHT 0x02A4 /* Dword offset A9 */ +#define SC_LEFT_RIGHT 0x02A8 /* Dword offset AA */ +#define SC_TOP 0x02AC /* Dword offset AB */ +#define SC_BOTTOM 0x02B0 /* Dword offset AC */ +#define SC_TOP_BOTTOM 0x02B4 /* Dword offset AD */ + +#define DP_BKGD_CLR 0x02C0 /* Dword offset B0 */ +#define DP_FRGD_CLR 0x02C4 /* Dword offset B1 */ +#define DP_WRITE_MASK 0x02C8 /* Dword offset B2 */ +#define DP_CHAIN_MASK 0x02CC /* Dword offset B3 */ +#define DP_PIX_WIDTH 0x02D0 /* Dword offset B4 */ +#define DP_MIX 0x02D4 /* Dword offset B5 */ +#define DP_SRC 0x02D8 /* Dword offset B6 */ + +#define CLR_CMP_CLR 0x0300 /* Dword offset C0 */ +#define CLR_CMP_MASK 0x0304 /* Dword offset C1 */ +#define CLR_CMP_CNTL 0x0308 /* Dword offset C2 */ + +#define FIFO_STAT 0x0310 /* Dword offset C4 */ + +#define CONTEXT_MASK 0x0320 /* Dword offset C8 */ +#define CONTEXT_LOAD_CNTL 0x032C /* Dword offset CB */ + +#define GUI_TRAJ_CNTL 0x0330 /* Dword offset CC */ +#define GUI_STAT 0x0338 /* Dword offset CE */ + + +/* CRTC control values (mostly CRTC_GEN_CNTL) */ + +#define CRTC_H_SYNC_NEG 0x00200000 +#define CRTC_V_SYNC_NEG 0x00200000 + +#define CRTC_DBL_SCAN_EN 0x00000001 +#define CRTC_INTERLACE_EN 0x00000002 +#define CRTC_HSYNC_DIS 0x00000004 +#define CRTC_VSYNC_DIS 0x00000008 +#define CRTC_CSYNC_EN 0x00000010 +#define CRTC_PIX_BY_2_EN 0x00000020 +#define CRTC_BLANK 0x00000040 + +#define CRTC_PIX_WIDTH_MASK 0x00000700 +#define CRTC_PIX_WIDTH_4BPP 0x00000100 +#define CRTC_PIX_WIDTH_8BPP 0x00000200 +#define CRTC_PIX_WIDTH_15BPP 0x00000300 +#define CRTC_PIX_WIDTH_16BPP 0x00000400 +#define CRTC_PIX_WIDTH_24BPP 0x00000500 +#define CRTC_PIX_WIDTH_32BPP 0x00000600 + +#define CRTC_BYTE_PIX_ORDER 0x00000800 +#define CRTC_PIX_ORDER_MSN_LSN 0x00000000 +#define CRTC_PIX_ORDER_LSN_MSN 0x00000800 + +#define CRTC_FIFO_LWM 0x000f0000 +#define CRTC_EXT_DISP_EN 0x01000000 +#define CRTC_EXT_EN 0x02000000 + +#define CRTC_CRNT_VLINE 0x07f00000 +#define CRTC_VBLANK 0x00000001 + +/* DAC control values */ + +#define DAC_EXT_SEL_RS2 0x01 +#define DAC_EXT_SEL_RS3 0x02 +#define DAC_8BIT_EN 0x00000100 +#define DAC_PIX_DLY_MASK 0x00000600 +#define DAC_PIX_DLY_0NS 0x00000000 +#define DAC_PIX_DLY_2NS 0x00000200 +#define DAC_PIX_DLY_4NS 0x00000400 +#define DAC_BLANK_ADJ_MASK 0x00001800 +#define DAC_BLANK_ADJ_0 0x00000000 +#define DAC_BLANK_ADJ_1 0x00000800 +#define DAC_BLANK_ADJ_2 0x00001000 + + +/* Mix control values */ + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +/* Maximum engine dimensions */ +#define ENGINE_MIN_X 0 +#define ENGINE_MIN_Y 0 +#define ENGINE_MAX_X 4095 +#define ENGINE_MAX_Y 16383 + +/* Mach64 engine bit constants - these are typically ORed together */ + +/* BUS_CNTL register constants */ +#define BUS_FIFO_ERR_ACK 0x00200000 +#define BUS_HOST_ERR_ACK 0x00800000 + +/* GEN_TEST_CNTL register constants */ +#define GEN_OVR_OUTPUT_EN 0x20 +#define HWCURSOR_ENABLE 0x80 +#define GUI_ENGINE_ENABLE 0x100 +#define BLOCK_WRITE_ENABLE 0x200 + +/* CLOCK_CNTL register constants */ +#define CLOCK_SEL 0x0f +#define CLOCK_DIV 0x30 +#define CLOCK_DIV1 0x00 +#define CLOCK_DIV2 0x10 +#define CLOCK_DIV4 0x20 +#define CLOCK_STROBE 0x40 +#define PLL_WR_EN 0x02 + +/* PLL registers */ +#define PLL_MACRO_CNTL 0x01 +#define PLL_REF_DIV 0x02 +#define PLL_GEN_CNTL 0x03 +#define MCLK_FB_DIV 0x04 +#define PLL_VCLK_CNTL 0x05 +#define VCLK_POST_DIV 0x06 +#define VCLK0_FB_DIV 0x07 +#define VCLK1_FB_DIV 0x08 +#define VCLK2_FB_DIV 0x09 +#define VCLK3_FB_DIV 0x0A +#define PLL_XCLK_CNTL 0x0B +#define PLL_TEST_CTRL 0x0E +#define PLL_TEST_COUNT 0x0F + +/* Fields in PLL registers */ +#define PLL_PC_GAIN 0x07 +#define PLL_VC_GAIN 0x18 +#define PLL_DUTY_CYC 0xE0 +#define PLL_OVERRIDE 0x01 +#define PLL_MCLK_RST 0x02 +#define OSC_EN 0x04 +#define EXT_CLK_EN 0x08 +#define MCLK_SRC_SEL 0x70 +#define EXT_CLK_CNTL 0x80 +#define VCLK_SRC_SEL 0x03 +#define PLL_VCLK_RST 0x04 +#define VCLK_INVERT 0x08 +#define VCLK0_POST 0x03 +#define VCLK1_POST 0x0C +#define VCLK2_POST 0x30 +#define VCLK3_POST 0xC0 + +/* CONFIG_CNTL register constants */ +#define APERTURE_4M_ENABLE 1 +#define APERTURE_8M_ENABLE 2 +#define VGA_APERTURE_ENABLE 4 + +/* CONFIG_STAT0 register constants (GX, CX) */ +#define CFG_BUS_TYPE 0x00000007 +#define CFG_MEM_TYPE 0x00000038 +#define CFG_INIT_DAC_TYPE 0x00000e00 + +/* CONFIG_STAT0 register constants (CT, ET, VT) */ +#define CFG_MEM_TYPE_xT 0x00000007 + +#define ISA 0 +#define EISA 1 +#define LOCAL_BUS 6 +#define PCI 7 + +/* Memory types for GX, CX */ +#define DRAMx4 0 +#define VRAMx16 1 +#define VRAMx16ssr 2 +#define DRAMx16 3 +#define GraphicsDRAMx16 4 +#define EnhancedVRAMx16 5 +#define EnhancedVRAMx16ssr 6 + +/* Memory types for CT, ET, VT, GT */ +#define DRAM 0 +#define EDO_DRAM 1 +#define PSEUDO_EDO 2 +#define SDRAM 3 + +#define DAC_INTERNAL 0x00 +#define DAC_IBMRGB514 0x01 +#define DAC_ATI68875 0x02 +#define DAC_TVP3026_A 0x72 +#define DAC_BT476 0x03 +#define DAC_BT481 0x04 +#define DAC_ATT20C491 0x14 +#define DAC_SC15026 0x24 +#define DAC_MU9C1880 0x34 +#define DAC_IMSG174 0x44 +#define DAC_ATI68860_B 0x05 +#define DAC_ATI68860_C 0x15 +#define DAC_TVP3026_B 0x75 +#define DAC_STG1700 0x06 +#define DAC_ATT498 0x16 +#define DAC_STG1702 0x07 +#define DAC_SC15021 0x17 +#define DAC_ATT21C498 0x27 +#define DAC_STG1703 0x37 +#define DAC_CH8398 0x47 +#define DAC_ATT20C408 0x57 + +#define CLK_ATI18818_0 0 +#define CLK_ATI18818_1 1 +#define CLK_STG1703 2 +#define CLK_CH8398 3 +#define CLK_INTERNAL 4 +#define CLK_ATT20C408 5 +#define CLK_IBMRGB514 6 + +/* MEM_CNTL register constants */ +#define MEM_SIZE_ALIAS 0x00000007 +#define MEM_SIZE_512K 0x00000000 +#define MEM_SIZE_1M 0x00000001 +#define MEM_SIZE_2M 0x00000002 +#define MEM_SIZE_4M 0x00000003 +#define MEM_SIZE_6M 0x00000004 +#define MEM_SIZE_8M 0x00000005 +#define MEM_SIZE_ALIAS_GTB 0x0000000F +#define MEM_SIZE_2M_GTB 0x00000003 +#define MEM_SIZE_4M_GTB 0x00000007 +#define MEM_SIZE_6M_GTB 0x00000009 +#define MEM_SIZE_8M_GTB 0x0000000B +#define MEM_BNDRY 0x00030000 +#define MEM_BNDRY_0K 0x00000000 +#define MEM_BNDRY_256K 0x00010000 +#define MEM_BNDRY_512K 0x00020000 +#define MEM_BNDRY_1M 0x00030000 +#define MEM_BNDRY_EN 0x00040000 + +/* ATI PCI constants */ +#define PCI_ATI_VENDOR_ID 0x1002 +#define PCI_MACH64_GX 0x4758 +#define PCI_MACH64_CX 0x4358 +#define PCI_MACH64_CT 0x4354 +#define PCI_MACH64_ET 0x4554 +#define PCI_MACH64_VT 0x5654 +#define PCI_MACH64_GT 0x4754 + +/* CONFIG_CHIP_ID register constants */ +#define CFG_CHIP_TYPE 0x0000FFFF +#define CFG_CHIP_CLASS 0x00FF0000 +#define CFG_CHIP_REV 0xFF000000 +#define CFG_CHIP_VERSION 0x07000000 +#define CFG_CHIP_FOUNDRY 0x38000000 +#define CFG_CHIP_REVISION 0xC0000000 + +/* Chip IDs read from CONFIG_CHIP_ID */ +#define MACH64_GX_ID 0xD7 +#define MACH64_CX_ID 0x57 +#define MACH64_CT_ID 0x4354 +#define MACH64_ET_ID 0x4554 +#define MACH64_VT_ID 0x5654 +#define MACH64_GT_ID 0x4754 + +/* Mach64 chip types */ +#define MACH64_UNKNOWN 0 +#define MACH64_GX 1 +#define MACH64_CX 2 +#define MACH64_CT 3 +#define MACH64_ET 4 +#define MACH64_VT 5 +#define MACH64_GT 6 + +/* DST_CNTL register constants */ +#define DST_X_RIGHT_TO_LEFT 0 +#define DST_X_LEFT_TO_RIGHT 1 +#define DST_Y_BOTTOM_TO_TOP 0 +#define DST_Y_TOP_TO_BOTTOM 2 +#define DST_X_MAJOR 0 +#define DST_Y_MAJOR 4 +#define DST_X_TILE 8 +#define DST_Y_TILE 0x10 +#define DST_LAST_PEL 0x20 +#define DST_POLYGON_ENABLE 0x40 +#define DST_24_ROTATION_ENABLE 0x80 + +/* SRC_CNTL register constants */ +#define SRC_PATTERN_ENABLE 1 +#define SRC_ROTATION_ENABLE 2 +#define SRC_LINEAR_ENABLE 4 +#define SRC_BYTE_ALIGN 8 +#define SRC_LINE_X_RIGHT_TO_LEFT 0 +#define SRC_LINE_X_LEFT_TO_RIGHT 0x10 + +/* HOST_CNTL register constants */ +#define HOST_BYTE_ALIGN 1 + +/* GUI_TRAJ_CNTL register constants */ +#define PAT_MONO_8x8_ENABLE 0x01000000 +#define PAT_CLR_4x2_ENABLE 0x02000000 +#define PAT_CLR_8x1_ENABLE 0x04000000 + +/* DP_CHAIN_MASK register constants */ +#define DP_CHAIN_4BPP 0x8888 +#define DP_CHAIN_7BPP 0xD2D2 +#define DP_CHAIN_8BPP 0x8080 +#define DP_CHAIN_8BPP_RGB 0x9292 +#define DP_CHAIN_15BPP 0x4210 +#define DP_CHAIN_16BPP 0x8410 +#define DP_CHAIN_24BPP 0x8080 +#define DP_CHAIN_32BPP 0x8080 + +/* DP_PIX_WIDTH register constants */ +#define DST_1BPP 0 +#define DST_4BPP 1 +#define DST_8BPP 2 +#define DST_15BPP 3 +#define DST_16BPP 4 +#define DST_32BPP 6 +#define SRC_1BPP 0 +#define SRC_4BPP 0x100 +#define SRC_8BPP 0x200 +#define SRC_15BPP 0x300 +#define SRC_16BPP 0x400 +#define SRC_32BPP 0x600 +#define HOST_1BPP 0 +#define HOST_4BPP 0x10000 +#define HOST_8BPP 0x20000 +#define HOST_15BPP 0x30000 +#define HOST_16BPP 0x40000 +#define HOST_32BPP 0x60000 +#define BYTE_ORDER_MSB_TO_LSB 0 +#define BYTE_ORDER_LSB_TO_MSB 0x1000000 + +/* DP_MIX register constants */ +#define BKGD_MIX_NOT_D 0 +#define BKGD_MIX_ZERO 1 +#define BKGD_MIX_ONE 2 +#define BKGD_MIX_D 3 +#define BKGD_MIX_NOT_S 4 +#define BKGD_MIX_D_XOR_S 5 +#define BKGD_MIX_NOT_D_XOR_S 6 +#define BKGD_MIX_S 7 +#define BKGD_MIX_NOT_D_OR_NOT_S 8 +#define BKGD_MIX_D_OR_NOT_S 9 +#define BKGD_MIX_NOT_D_OR_S 10 +#define BKGD_MIX_D_OR_S 11 +#define BKGD_MIX_D_AND_S 12 +#define BKGD_MIX_NOT_D_AND_S 13 +#define BKGD_MIX_D_AND_NOT_S 14 +#define BKGD_MIX_NOT_D_AND_NOT_S 15 +#define BKGD_MIX_D_PLUS_S_DIV2 0x17 +#define FRGD_MIX_NOT_D 0 +#define FRGD_MIX_ZERO 0x10000 +#define FRGD_MIX_ONE 0x20000 +#define FRGD_MIX_D 0x30000 +#define FRGD_MIX_NOT_S 0x40000 +#define FRGD_MIX_D_XOR_S 0x50000 +#define FRGD_MIX_NOT_D_XOR_S 0x60000 +#define FRGD_MIX_S 0x70000 +#define FRGD_MIX_NOT_D_OR_NOT_S 0x80000 +#define FRGD_MIX_D_OR_NOT_S 0x90000 +#define FRGD_MIX_NOT_D_OR_S 0xa0000 +#define FRGD_MIX_D_OR_S 0xb0000 +#define FRGD_MIX_D_AND_S 0xc0000 +#define FRGD_MIX_NOT_D_AND_S 0xd0000 +#define FRGD_MIX_D_AND_NOT_S 0xe0000 +#define FRGD_MIX_NOT_D_AND_NOT_S 0xf0000 +#define FRGD_MIX_D_PLUS_S_DIV2 0x170000 + +/* DP_SRC register constants */ +#define BKGD_SRC_BKGD_CLR 0 +#define BKGD_SRC_FRGD_CLR 1 +#define BKGD_SRC_HOST 2 +#define BKGD_SRC_BLIT 3 +#define BKGD_SRC_PATTERN 4 +#define FRGD_SRC_BKGD_CLR 0 +#define FRGD_SRC_FRGD_CLR 0x100 +#define FRGD_SRC_HOST 0x200 +#define FRGD_SRC_BLIT 0x300 +#define FRGD_SRC_PATTERN 0x400 +#define MONO_SRC_ONE 0 +#define MONO_SRC_PATTERN 0x10000 +#define MONO_SRC_HOST 0x20000 +#define MONO_SRC_BLIT 0x30000 + +/* CLR_CMP_CNTL register constants */ +#define COMPARE_FALSE 0 +#define COMPARE_TRUE 1 +#define COMPARE_NOT_EQUAL 4 +#define COMPARE_EQUAL 5 +#define COMPARE_DESTINATION 0 +#define COMPARE_SOURCE 0x1000000 + +/* FIFO_STAT register constants */ +#define FIFO_ERR 0x80000000 + +/* CONTEXT_LOAD_CNTL constants */ +#define CONTEXT_NO_LOAD 0 +#define CONTEXT_LOAD 0x10000 +#define CONTEXT_LOAD_AND_DO_FILL 0x20000 +#define CONTEXT_LOAD_AND_DO_LINE 0x30000 +#define CONTEXT_EXECUTE 0 +#define CONTEXT_CMD_DISABLE 0x80000000 + +/* GUI_STAT register constants */ +#define ENGINE_IDLE 0 +#define ENGINE_BUSY 1 +#define SCISSOR_LEFT_FLAG 0x10 +#define SCISSOR_RIGHT_FLAG 0x20 +#define SCISSOR_TOP_FLAG 0x40 +#define SCISSOR_BOTTOM_FLAG 0x80 + +/* ATI VGA Extended Regsiters */ +#define sioATIEXT 0x1ce +#define bioATIEXT 0x3ce + +#define ATI2E 0xae +#define ATI32 0xb2 +#define ATI36 0xb6 + +/* VGA Graphics Controller Registers */ +#define VGAGRA 0x3ce +#define GRA06 0x06 + +/* VGA Seququencer Registers */ +#define VGASEQ 0x3c4 +#define SEQ02 0x02 +#define SEQ04 0x04 + +#define MACH64_MAX_X ENGINE_MAX_X +#define MACH64_MAX_Y ENGINE_MAX_Y + +#define INC_X 0x0020 +#define INC_Y 0x0080 + +#define RGB16_555 0x0000 +#define RGB16_565 0x0040 +#define RGB16_655 0x0080 +#define RGB16_664 0x00c0 + +#define POLY_TEXT_TYPE 0x0001 +#define IMAGE_TEXT_TYPE 0x0002 +#define TEXT_TYPE_8_BIT 0x0004 +#define TEXT_TYPE_16_BIT 0x0008 +#define POLY_TEXT_TYPE_8 (POLY_TEXT_TYPE | TEXT_TYPE_8_BIT) +#define IMAGE_TEXT_TYPE_8 (IMAGE_TEXT_TYPE | TEXT_TYPE_8_BIT) +#define POLY_TEXT_TYPE_16 (POLY_TEXT_TYPE | TEXT_TYPE_16_BIT) +#define IMAGE_TEXT_TYPE_16 (IMAGE_TEXT_TYPE | TEXT_TYPE_16_BIT) + +#define MACH64_NUM_CLOCKS 16 +#define MACH64_NUM_FREQS 50 + +/* Wait until "v" queue entries are free */ +#define aty_WaitQueue(v) { while ((aty_ld_rev(FIFO_STAT) & 0xffff) > \ + ((unsigned short)(0x8000 >> (v)))); } + +/* Wait until GP is idle and queue is empty */ +#define aty_WaitIdleEmpty() { aty_WaitQueue(16); \ + while ((aty_ld_rev(GUI_STAT) & 1) != 0); } + +#define SKIP_2(_v) ((((_v)<<1)&0xfff8)|((_v)&0x3)|(((_v)&0x80)>>5)) + +#define MACH64_BIT_BLT(_srcx, _srcy, _dstx, _dsty, _w, _h, _dir) \ +{ \ + aty_WaitQueue(5); \ + aty_st_rev(SRC_Y_X, (((_srcx) << 16) | ((_srcy) & 0x0000ffff))); \ + aty_st_rev(SRC_WIDTH1, (_w)); \ + aty_st_rev(DST_CNTL, (_dir)); \ + aty_st_rev(DST_Y_X, (((_dstx) << 16) | ((_dsty) & 0x0000ffff))); \ + aty_st_rev(DST_HEIGHT_WIDTH, (((_w) << 16) | ((_h) & 0x0000ffff))); \ +} +#endif /* REGMACH64_H */ + diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/control.c linux/drivers/macintosh/control.c --- v2.1.50/linux/drivers/macintosh/control.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/control.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,520 @@ +/* + * control.c: Console support for PowerMac "control" display adaptor. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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 +#include +#include +#include "pmac-cons.h" +#include "control.h" + +/* + * Structure of the registers for the RADACAL colormap device. + */ +struct cmap_regs { + unsigned char addr; + char pad1[15]; + unsigned char d1; + char pad2[15]; + unsigned char d2; + char pad3[15]; + unsigned char lut; + char pad4[15]; +}; + +/* + * Structure of the registers for the "control" display adaptor". + */ +#define PAD(x) char x[12] + +struct preg { /* padded register */ + unsigned r; + char pad[12]; +}; + +struct control_regs { + struct preg vcount; /* vertical counter */ + /* Vertical parameters are in units of 1/2 scan line */ + struct preg vswin; /* between vsblank and vssync */ + struct preg vsblank; /* vert start blank */ + struct preg veblank; /* vert end blank (display start) */ + struct preg vewin; /* between vesync and veblank */ + struct preg vesync; /* vert end sync */ + struct preg vssync; /* vert start sync */ + struct preg vperiod; /* vert period */ + struct preg reg8; + /* Horizontal params are in units of 2 pixels */ + struct preg hperiod; /* horiz period - 2 */ + struct preg hsblank; /* horiz start blank */ + struct preg heblank; /* horiz end blank */ + struct preg hesync; /* horiz end sync */ + struct preg hssync; /* horiz start sync */ + struct preg rege; + struct preg regf; + struct preg reg10; + struct preg reg11; + struct preg ctrl; /* display control */ + struct preg start_addr; /* start address: 5 lsbs zero */ + struct preg pitch; /* addrs diff between scan lines */ + struct preg mon_sense; /* monitor sense bits */ + struct preg flags; + struct preg mode; + struct preg reg18; + struct preg reg19; + struct preg res[6]; +}; + +static void set_control_clock(unsigned char *params); +static int read_control_sense(void); +static int control_vram_reqd(int vmode, int cmode); + +static int total_vram; /* total amount of video memory, bytes */ +static unsigned char *frame_buffer; +static struct cmap_regs *cmap_regs; +static struct control_regs *disp_regs; +static int control_use_bank2; + +/* + * Register initialization tables for the control display. + * + * Dot clock rate is + * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0]. + * + * The values for vertical frequency (V) in the comments below + * are the values measured using the modes under MacOS. + */ +struct control_regvals { + int pitch[3]; /* bytes/line, indexed by color_mode */ + int offset[3]; /* first pixel address */ + unsigned regs[16]; /* for vswin .. reg10 */ + unsigned char mode[3]; /* indexed by color_mode */ + unsigned char radacal_ctrl[3]; + unsigned char clock_params[3]; +}; + +/* Register values for 1280x1024, 75Hz mode (20) */ +static struct control_regvals control_reg_init_20 = { + { 1280, 2560, 0 }, + { 0x10, 0x20, 0 }, + { 2129, 2128, 80, 42, 4, 2130, 2132, 88, + 420, 411, 91, 35, 421, 18, 211, 386, }, + { 1, 1, 1}, + { 0x50, 0x64, 0x64 }, + { 13, 56, 3 } /* pixel clock = 134.61MHz for V=74.81Hz */ +}; + +/* Register values for 1280x960, 75Hz mode (19) */ +static struct control_regvals control_reg_init_19 = { + { 1280, 2560, 0 }, + { 0x10, 0x20, 0 }, + { 1997, 1996, 76, 40, 4, 1998, 2000, 86, + 418, 409, 89, 35, 419, 18, 210, 384, }, + { 1, 1, 1 }, + { 0x50, 0x64, 0x64 }, + { 31, 125, 3 } /* pixel clock = 126.01MHz for V=75.01 Hz */ +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct control_regvals control_reg_init_18 = { + { 1152, 2304, 4608 }, + { 0x10, 0x28, 0x50 }, + { 1825, 1822, 82, 43, 4, 1828, 1830, 120, + 726, 705, 129, 63, 727, 32, 364, 664 }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 19, 61, 3 } /* pixel clock = 100.33MHz for V=75.31Hz */ +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct control_regvals control_reg_init_17 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1603, 1600, 64, 34, 4, 1606, 1608, 120, + 662, 641, 129, 47, 663, 24, 332, 616 }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 11, 28, 3 } /* pixel clock = 79.55MHz for V=74.50Hz */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct control_regvals control_reg_init_15 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1607, 1604, 68, 39, 10, 1610, 1612, 132, + 670, 653, 141, 67, 671, 34, 336, 604, }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 12, 30, 3 } /* pixel clock = 78.12MHz for V=72.12Hz */ +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct control_regvals control_reg_init_14 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1607, 1604, 68, 39, 10, 1610, 1612, 132, + 670, 653, 141, 67, 671, 34, 336, 604, }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 15, 31, 3 } /* pixel clock = 64.58MHz for V=59.62Hz */ +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct control_regvals control_reg_init_13 = { + { 832, 1664, 3328 }, + { 0x10, 0x28, 0x50 }, + { 1331, 1330, 82, 43, 4, 1332, 1334, 128, + 574, 553, 137, 31, 575, 16, 288, 544 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 23, 42, 3 } /* pixel clock = 57.07MHz for V=74.27Hz */ +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct control_regvals control_reg_init_12 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1247, 1246, 46, 25, 4, 1248, 1250, 104, + 526, 513, 113, 39, 527, 20, 264, 488, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 7, 11, 3 } /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct control_regvals control_reg_init_11 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1293, 1256, 56, 33, 10, 1330, 1332, 76, + 518, 485, 85, 59, 519, 30, 260, 460, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 17, 27, 3 } /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct control_regvals control_reg_init_10 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1293, 1256, 56, 33, 10, 1330, 1332, 76, + 518, 485, 85, 59, 519, 30, 260, 460, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 20, 53, 2 } /* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct control_regvals control_reg_init_7 = { + { 640, 1280, 2560 }, + { 0x10, 0x30, 0x68 }, + { 0x727, 0x724, 0x58, 0x2e, 0x4, 0x72a, 0x72c, 0x40, + 0x19e, 0x18c, 0x4c, 0x27, 0x19f, 0x14, 0xd0, 0x178 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 9, 33, 2 } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct control_regvals control_reg_init_6 = { + { 640, 1280, 2560 }, + { 0, 8, 0x10 }, + { 1045, 1042, 82, 43, 4, 1048, 1050, 72, + 430, 393, 73, 31, 431, 16, 216, 400 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 14, 27, 2 } /* pixel clock = 30.13MHz for V=66.43Hz */ +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct control_regvals control_reg_init_5 = { + { 640, 1280, 2560 }, + { 0x10, 0x28, 0x50 }, + { 1037, 1026, 66, 34, 2, 1048, 1050, 56, + 398, 385, 65, 47, 399, 24, 200, 352, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 23, 37, 2 } /* pixel clock = 25.14MHz for V=59.85Hz */ +}; + +static struct control_regvals *control_reg_init[20] = { + NULL, NULL, NULL, NULL, + &control_reg_init_5, + &control_reg_init_6, + &control_reg_init_7, + NULL, NULL, + &control_reg_init_10, + &control_reg_init_11, + &control_reg_init_12, + &control_reg_init_13, + &control_reg_init_14, + &control_reg_init_15, + NULL, + &control_reg_init_17, + &control_reg_init_18, + &control_reg_init_19, + &control_reg_init_20 +}; + +/* + * Get the monitor sense value. + * Note that this can be called before calibrate_delay, + * so we can't use udelay. + */ +static int +read_control_sense() +{ + int sense; + + out_le32(&disp_regs->mon_sense.r, 7); /* drive all lines high */ + __delay(200); + out_le32(&disp_regs->mon_sense.r, 077); /* turn off drivers */ + __delay(2000); + sense = (in_le32(&disp_regs->mon_sense.r) & 0x1c0) << 2; + + /* drive each sense line low in turn and collect the other 2 */ + out_le32(&disp_regs->mon_sense.r, 033); /* drive A low */ + __delay(2000); + sense |= (in_le32(&disp_regs->mon_sense.r) & 0xc0) >> 2; + out_le32(&disp_regs->mon_sense.r, 055); /* drive B low */ + __delay(2000); + sense |= ((in_le32(&disp_regs->mon_sense.r) & 0x100) >> 5) + | ((in_le32(&disp_regs->mon_sense.r) & 0x40) >> 4); + out_le32(&disp_regs->mon_sense.r, 066); /* drive C low */ + __delay(2000); + sense |= (in_le32(&disp_regs->mon_sense.r) & 0x180) >> 7; + + out_le32(&disp_regs->mon_sense.r, 077); /* turn off drivers */ + return sense; +} + +static inline int control_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * control_reg_init[vmode-1]->pitch[cmode]; +} + +void +map_control_display(struct device_node *dp) +{ + int i, sense; + unsigned long addr, size; + int bank1, bank2; + + if (dp->next != 0) + printk("Warning: only using first control display device\n"); + if (dp->n_addrs != 2) + panic("expecting 2 addresses for control (got %d)", dp->n_addrs); + +#if 0 + printk("pmac_display_init: node = %p, addrs =", dp->node); + for (i = 0; i < dp->n_addrs; ++i) + printk(" %x(%x)", dp->addrs[i].address, dp->addrs[i].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i]); + printk("\n"); +#endif + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x800000) { + /* use the big-endian aperture (??) */ + addr += 0x800000; + /* map at most 8MB for the frame buffer */ + frame_buffer = ioremap(addr, 0x800000); + } else { + disp_regs = ioremap(addr, size); + } + } + cmap_regs = ioremap(0xf301b000, 0x1000); /* XXX not in prom? */ + + /* Work out which banks of VRAM we have installed. */ + frame_buffer[0] = 0x5a; + frame_buffer[1] = 0xc7; + bank1 = frame_buffer[0] == 0x5a && frame_buffer[1] == 0xc7; + frame_buffer[0x600000] = 0xa5; + frame_buffer[0x600001] = 0x38; + bank2 = frame_buffer[0x600000] == 0xa5 && frame_buffer[0x600001] == 0x38; + total_vram = (bank1 + bank2) * 0x200000; + /* If we don't have bank 1 installed, we hope we have bank 2 :-) */ + control_use_bank2 = !bank1; + if (control_use_bank2) + frame_buffer += 0x600000; + + sense = read_control_sense(); + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || control_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (control_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_60; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + while (color_mode > CMODE_8 + && control_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + + printk("Monitor sense value = 0x%x, ", sense); +} + +static void +set_control_clock(unsigned char *params) +{ + struct cuda_request req; + int i; + + for (i = 0; i < 3; ++i) { + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x50, i + 1, params[i]); + while (!req.got_reply) + cuda_poll(); + } +} + +void +control_init() +{ + struct preg *rp; + int i, yoff, hres; + int ctrl, flags; + unsigned *p; + struct control_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = control_reg_init[video_mode-1]) == 0) + panic("control: display mode %d not supported", video_mode); + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + row_pitch = line_pitch * 16; + + if (control_vram_reqd(video_mode, color_mode) > 0x200000) + flags = 0x51; + else if (control_use_bank2) + flags = 0x39; + else + flags = 0x31; + if (video_mode >= VMODE_1280_960_75 && color_mode >= CMODE_16) + ctrl = 0x7f; + else + ctrl = 0x3b; + + /* Initialize display timing registers */ + out_le32(&disp_regs->ctrl.r, 0x43b); + set_control_clock(init->clock_params); + cmap_regs->addr = 0x20; cmap_regs->d2 = init->radacal_ctrl[color_mode]; + cmap_regs->addr = 0x21; cmap_regs->d2 = control_use_bank2? 0: 1; + cmap_regs->addr = 0x10; cmap_regs->d2 = 0; + cmap_regs->addr = 0x11; cmap_regs->d2 = 0; + rp = &disp_regs->vswin; + for (i = 0; i < 16; ++i, ++rp) + out_le32(&rp->r, init->regs[i]); + out_le32(&disp_regs->pitch.r, line_pitch); + out_le32(&disp_regs->mode.r, init->mode[color_mode]); + out_le32(&disp_regs->flags.r, flags); + out_le32(&disp_regs->start_addr.r, 0); + out_le32(&disp_regs->reg18.r, 0x1e5); + out_le32(&disp_regs->reg19.r, 0); + + pmac_init_palette(); /* Initialize colormap */ + + /* Turn on display */ + out_le32(&disp_regs->ctrl.r, ctrl); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + init->offset[color_mode]; + + /* Clear screen */ + p = (unsigned *) (frame_buffer + init->offset[color_mode]); + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "control", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + init->offset[color_mode]; + display_info.cmap_adr_address = (unsigned long) &cmap_regs->addr; + display_info.cmap_data_address = (unsigned long) &cmap_regs->lut; + display_info.disp_reg_address = (unsigned long) &disp_regs; +} + +int +control_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || control_reg_init[mode->mode-1] == 0) + return -EINVAL; + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (control_vram_reqd(mode->mode, cmode) > total_vram) + return -EINVAL; + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + control_init(); + } + return 0; +} + +void +control_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + cmap_regs->addr = index + i; eieio(); + cmap_regs->lut = red[i]; eieio(); + cmap_regs->lut = green[i]; eieio(); + cmap_regs->lut = blue[i]; eieio(); + } +} + +void +control_set_blanking(int blank_mode) +{ + int ctrl; + + ctrl = ld_le32(&disp_regs->ctrl.r) | 0x33; + if (blank_mode & VESA_VSYNC_SUSPEND) + ctrl &= ~3; + if (blank_mode & VESA_HSYNC_SUSPEND) + ctrl &= ~0x30; + out_le32(&disp_regs->ctrl.r, ctrl); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/control.h linux/drivers/macintosh/control.h --- v2.1.50/linux/drivers/macintosh/control.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/control.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,17 @@ +/* + * Exported procedures for the "control" display driver on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern void map_control_display(struct device_node *); +extern void control_init(void); +extern int control_setmode(struct vc_mode *mode, int doit); +extern void control_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void control_set_blanking(int blank_mode); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/imstt.c linux/drivers/macintosh/imstt.c --- v2.1.50/linux/drivers/macintosh/imstt.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/imstt.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,506 @@ +/* + * imstt.c: Console support for PowerMac "imstt" display adaptor. + * + * Copyright (C) 1997 Sigurdur Asgeirsson + * + * 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 +#include +#include +#include +#include +#include +#include "pmac-cons.h" +#include "imstt.h" + +enum +{ + S1SA = 0, /* 0x00 */ + S2SA = 1, /* 0x04 */ + SP = 2, /* 0x08 */ + DSA = 3, /* 0x0C */ + CNT = 4, /* 0x10 */ + DP_OCTRL = 5, /* 0x14 */ + BLTCTL = 10, /* 0x28 */ + + // Scan Timing Generator Registers + HES = 12, /* 0x30 */ + HEB = 13, /* 0x34 */ + HSB = 14, /* 0x38 */ + HT = 15, /* 0x3C */ + VES = 16, /* 0x40 */ + VEB = 17, /* 0x44 */ + VSB = 18, /* 0x48 */ + VT = 19, /* 0x4C */ + HCIV = 20, /* 0x50 */ + VCIV = 21, /* 0x54 */ + TCDR = 22, /* 0x58 */ + VIL = 23, /* 0x5C */ + STGCTL = 24, /* 0x60 */ + + // Screen Refresh Generator Registers + SSR = 25, /* 0x64 */ + HRIR = 26, /* 0x68 */ + SPR = 27, /* 0x6C */ + CMR = 28, /* 0x70 */ + SRGCTL = 29, /* 0x74 */ + + // RAM Refresh Generator Registers + RRCIV = 30, /* 0x78 */ + RRSC = 31, /* 0x7C */ + RRCR = 34, /* 0x88 */ + + // System Registers + GIOE = 32, /* 0x80 */ + GIO = 33, /* 0x84 */ + SCR = 35, /* 0x8C */ + SSTATUS = 36, /* 0x90 */ + PRC = 37, /* 0x94 */ + +#if 0 + // PCI Registers + DVID = 0x00000000L, + SC = 0x00000004L, + CCR = 0x00000008L, + OG = 0x0000000CL, + BARM = 0x00000010L, + BARER = 0x00000030L, +#endif +}; + +enum +{ + PADDRW = 0x00, + PDATA = 0x04, + PPMASK = 0x08, + PADDRR = 0x0C, + PIDXLO = 0x10, + PIDXHI = 0x14, + PIDXDATA = 0x18, + PIDXCTL = 0x1C, + + PPIXREP = 0x0A, + PM0 = 0x20, + PN0 = 0x21, + PP0 = 0x22, + PC0 = 0x23 +}; + +struct initvalues +{ + unsigned char addr, value; +}; + +static struct initvalues initregs[] = +{ + { 0x02, 0x21 }, /* (0x01) Miscellaneous Clock Control */ + { 0x03, 0x00 }, /* (0x00) Sync Control */ + { 0x04, 0x00 }, /* (0x00) Horizontal Sync Position */ + { 0x05, 0x00 }, /* (0x00) Power Management */ + { 0x06, 0x0B }, /* (0x02) DAC Operation */ + { 0x07, 0x00 }, /* (0x00) Palette Control */ + { 0x08, 0x01 }, /* (0x01) System Clock Control */ + { 0x0B, 0x00 }, /* (U) 8 BPP Control */ + { 0x0C, 0xC4 }, /* (U) 16 BPP Control */ + { 0x0D, 0x00 }, /* (U) 24 BPP Packed Control */ + { 0x0E, 0x03 }, /* (U) 32 BPP Control */ + { 0x10, 0x05 }, /* (0x00) Pixel PLL Control 1 */ + { 0x11, 0x00 }, /* (0x00) Pixel PLL Control 2 */ + { 0x15, 0x08 }, /* (0x08) SYSCLK N (System PLL Reference Divider) */ + { 0x16, 0x57 }, /* (0x41) SYSCLK M (System PLL VCO Divider) */ + { 0x17, 0x00 }, /* (U) SYSCLK P */ + { 0x18, 0x00 }, /* (U) SYSCLK C */ + { 0x30, 0x00 }, /* (0x00) Cursor Control */ + { 0x60, 0xFF }, /* (U) Border Color Red */ + { 0x61, 0xFF }, /* (U) Border Color Green */ + { 0x62, 0xFF }, /* (U) Border Color Blue */ + { 0x70, 0x01 }, /* (0x00) Miscellaneous Control 1 */ + { 0x71, 0x45 }, /* (0x00) Miscellaneous Control 2 */ + { 0x72, 0x00 }, /* (0x00) Miscellaneous Control 3 */ + { 0x78, 0x00 }, /* (0x00) Key Control/DB Operation */ +}; + +static void set_imstt_clock(unsigned char *params); +static int read_imstt_sense(void); +static int imstt_vram_reqd(int vmode, int cmode); + +static int total_vram = 2 * 1024 * 1024; /* total amount of video memory, bytes */ +static unsigned char *frame_buffer; +static unsigned char *cmap_regs; +static unsigned *dc_regs; + + +/* + * Register initialization tables for the imstt display. + * + * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1) + * where m = clk[0], n = clk[1], p = clk[2] + * clk[3] is c, charge pump bias which depends on the VCO frequency + */ +struct imstt_regvals { + unsigned short cfg[8]; + unsigned char clk[4]; + unsigned long pitch[3]; +} imsttmode; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct imstt_regvals imstt_reg_init_17 = { + { 0x0A, 0x1C, 0x9C, 0xA6, 0x0003, 0x0020, 0x0320, 0x0323 }, + { 0x07, 0x00, 0x01, 0x02 }, + { 0x0400, 0x0800, 0x1000 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct imstt_regvals imstt_reg_init_13 = { + { 0x05, 0x20, 0x88, 0x90, 0x0003, 0x0028, 0x0298, 0x029B }, + { 0x3E, 0x0A, 0x01, 0x02 }, + { 832, 832 * 2, 832 * 4 } +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct imstt_regvals imstt_reg_init_6 = { + { 0x08, 0x12, 0x62, 0x6C, 0x0003, 0x002A, 0x020A, 0x020C }, + { 0x78, 0x13, 0x02, 0x02 }, + { 640, 640 * 2, 640 * 4 } +}; + +static struct imstt_regvals *imstt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &imstt_reg_init_6, // fake'm out + &imstt_reg_init_6, + NULL, NULL, NULL, + NULL, NULL, NULL, + &imstt_reg_init_13, + NULL, NULL, NULL, + &imstt_reg_init_17, + NULL, NULL, NULL +}; + +/* + * Get the monitor sense value. + * Note that this can be called before calibrate_delay, + * so we can't use udelay. + */ +static int +read_imstt_sense() +{ +#if 0 + int sense; + unsigned gio, gioe; + + gio = ld_le32(dc_regs + GIO) & ~0x0038; + gioe = ld_le32(dc_ + + out_le32(dc_regs + GIOE, reg); /* drive all lines high */ + __delay(200); + out_le32(dc_regs + GIOE, 077); /* turn off drivers */ + __delay(2000); + sense = (in_le32(dc_regs + GIOE) & 0x1c0) << 2; + + /* drive each sense line low in turn and collect the other 2 */ + out_le32(dc_regs + GIOE, 033); /* drive A low */ + __delay(2000); + sense |= (in_le32(dc_regs + GIOE) & 0xc0) >> 2; + out_le32(dc_regs + GIOE, 055); /* drive B low */ + __delay(2000); + sense |= ((in_le32(dc_regs + GIOE) & 0x100) >> 5) + | ((in_le32(dc_regs + GIOE) & 0x40) >> 4); + out_le32(dc_regs + GIOE, 066); /* drive C low */ + __delay(2000); + sense |= (in_le32(dc_regs + GIOE) & 0x180) >> 7; + + out_le32(dc_regs + GIOE, 077); /* turn off drivers */ + return sense; +#else + return 0; +#endif +} + +static inline int imstt_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * imstt_reg_init[vmode-1]->pitch[cmode]; +} + +void +map_imstt_display(struct device_node *dp) +{ + int i, sense; + unsigned long addr, size, tmp; + unsigned char bus, devfn; + unsigned short cmd; + + if (dp->next != 0) + printk("Warning: only using first imstt display device\n"); + +#if 1 + printk("pmac_display_init: node = %p, addrs =", dp->node); + for (i = 0; i < dp->n_addrs; ++i) + printk(" %x(%x)", dp->addrs[i].address, dp->addrs[i].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i]); + printk("\n"); +#endif + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x02000000) { + frame_buffer = ioremap(addr, size); + dc_regs = (unsigned*)(frame_buffer + 0x00800000); + cmap_regs = (unsigned char*)(frame_buffer + 0x00840000); + + printk("mapped frame_buffer=%x(%x)", (unsigned)frame_buffer, (unsigned)size); + printk(" dc_regs=%x, cmap_regs=%x\n", (unsigned)dc_regs, (unsigned)cmap_regs); + } + } + + /* enable memory-space accesses using config-space command register */ + if (pci_device_loc(dp, &bus, &devfn) == 0) { + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + + printk("command word 0x%04X\n", cmd); + + if (cmd != 0xffff) { + cmd |= PCI_COMMAND_MEMORY; + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + } + } + else + printk("unable to find pci device\n"); + + tmp = in_le32(dc_regs + SSTATUS); + printk("chip version %ld, ", (tmp & 0x0F00) >> 8); + + tmp = in_le32(dc_regs + PRC); + total_vram = (tmp & 0x0004) ? 0x000400000L : 0x000200000L; + printk("VRAM size %ldM\n", total_vram / 0x000100000L); + + sense = read_imstt_sense(); + printk("Monitor sense value = 0x%x, ", sense); +#if 0 + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || imstt_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (imstt_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_67; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + while (color_mode > CMODE_8 + && imstt_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + +#endif + + video_mode = VMODE_640_480_67; + color_mode = CMODE_8; +} + +static void +set_imstt_clock(unsigned char *params) +{ + cmap_regs[PIDXHI] = 0; eieio(); + cmap_regs[PIDXLO] = PM0; eieio(); + cmap_regs[PIDXDATA] = params[0]; eieio(); + + cmap_regs[PIDXLO] = PN0; eieio(); + cmap_regs[PIDXDATA] = params[1]; eieio(); + + cmap_regs[PIDXLO] = PP0; eieio(); + cmap_regs[PIDXDATA] = params[2]; eieio(); + + cmap_regs[PIDXLO] = PC0; eieio(); + cmap_regs[PIDXDATA] = params[3]; eieio(); +} + +void +imstt_init() +{ + int i, yoff, hres; + unsigned long ctl, pitch, tmp; + unsigned char pformat; + unsigned *p; + struct imstt_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = imstt_reg_init[video_mode-1]) == 0) + panic("imstt: display mode %d not supported", video_mode); + + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + row_pitch = line_pitch * 16; + + /* initialize the card */ + tmp = in_le32(dc_regs + STGCTL); + out_le32(dc_regs + STGCTL, tmp & ~0x1); +#if 0 + out_le32(dc_regs + SCR, 0); +#endif + + cmap_regs[PPMASK] = 0xFF; + /* set default values for DAC registers */ + cmap_regs[PIDXHI] = 0; eieio(); + for(i = 0; i < sizeof(initregs) / sizeof(*initregs); i++) { + cmap_regs[PIDXLO] = initregs[i].addr; eieio(); + cmap_regs[PIDXDATA] = initregs[i].value; eieio(); + } + set_imstt_clock(init->clk); + + switch(color_mode) { + case CMODE_32: + ctl = 0x17b5; + pitch = init->pitch[2] / 4; + pformat = 0x06; + break; + case CMODE_16: + ctl = 0x17b3; + pitch = init->pitch[1] / 4; + pformat = 0x04; + break; + case CMODE_8: + default: + ctl = 0x17b1; + pitch = init->pitch[0] / 4; + pformat = 0x03; + break; + } + + out_le32(&dc_regs[HES], init->cfg[0]); + out_le32(&dc_regs[HEB], init->cfg[1]); + out_le32(&dc_regs[HSB], init->cfg[2]); + out_le32(&dc_regs[HT], init->cfg[3]); + out_le32(&dc_regs[VES], init->cfg[4]); + out_le32(&dc_regs[VEB], init->cfg[5]); + out_le32(&dc_regs[VSB], init->cfg[6]); + out_le32(&dc_regs[VT], init->cfg[7]); + out_le32(&dc_regs[HCIV], 1); + out_le32(&dc_regs[VCIV], 1); + out_le32(&dc_regs[TCDR], 4); + out_le32(&dc_regs[VIL], 0); + + out_le32(&dc_regs[SSR], 0); + out_le32(&dc_regs[HRIR], 0x0200); + out_le32(&dc_regs[CMR], 0x01FF); + out_le32(&dc_regs[SRGCTL], 0x0003); + if(total_vram == 0x000200000) + out_le32(&dc_regs[SCR], 0x0059D); + else { + pitch /= 2; + out_le32(&dc_regs[SCR], 0x00D0DC); + } + + out_le32(&dc_regs[SPR], pitch); + + cmap_regs[PIDXLO] = PPIXREP; eieio(); + cmap_regs[PIDXDATA] = pformat; eieio(); + + + pmac_init_palette(); /* Initialize colormap */ + + out_le32(&dc_regs[STGCTL], ctl); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch; + + /* Clear screen */ + p = (unsigned *)frame_buffer; + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer; + display_info.cmap_adr_address = (unsigned long) &cmap_regs[PADDRW]; + display_info.cmap_data_address = (unsigned long) &cmap_regs[PDATA]; + display_info.disp_reg_address = (unsigned long) NULL; +} + +int +imstt_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || imstt_reg_init[mode->mode-1] == 0) + return -EINVAL; + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (imstt_vram_reqd(mode->mode, cmode) > total_vram) + return -EINVAL; + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + imstt_init(); + } + return 0; +} + +void +imstt_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + cmap_regs[PADDRW] = index + i; eieio(); + cmap_regs[PDATA] = red[i]; eieio(); + cmap_regs[PDATA] = green[i]; eieio(); + cmap_regs[PDATA] = blue[i]; eieio(); + } +} + +void +imstt_set_blanking(int blank_mode) +{ + long ctrl; + + ctrl = ld_le32(dc_regs + STGCTL) | 0x0030; + if (blank_mode & VESA_VSYNC_SUSPEND) + ctrl &= ~0x0020; + if (blank_mode & VESA_HSYNC_SUSPEND) + ctrl &= ~0x0010; + out_le32(dc_regs + STGCTL, ctrl); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/imstt.h linux/drivers/macintosh/imstt.h --- v2.1.50/linux/drivers/macintosh/imstt.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/imstt.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,18 @@ +/* + * Exported procedures for the "control" display driver on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern void map_imstt_display(struct device_node *); +extern void imstt_init(void); +extern int imstt_setmode(struct vc_mode *mode, int doit); +extern void imstt_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void imstt_set_blanking(int blank_mode); + diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.1.50/linux/drivers/macintosh/mac_keyb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/mac_keyb.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,343 @@ +/* + * drivers/char/mac_keyb.c + * + * Keyboard driver for Power Macintosh computers. + * + * Adapted from drivers/char/keyboard.c by Paul Mackerras + * (see that file for its authors and contributors). + * + * Copyright (C) 1996 Paul Mackerras. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define KEYB_KEYREG 0 /* register # for key up/down data */ +#define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ +#define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ + +unsigned char kbd_read_mask = 0; /* XXX */ + +static void kbd_repeat(unsigned long); +static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat }; +static int last_keycode; + +static void keyboard_input(unsigned char *, int, struct pt_regs *); +static void input_keycode(int, int); +static void leds_done(struct cuda_request *); + +extern struct kbd_struct kbd_table[]; + +extern void handle_scancode(unsigned char); +extern void put_queue(int); + +/* this map indicates which keys shouldn't autorepeat. */ +static unsigned char dont_repeat[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +int mackbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + return -EINVAL; +} + +int mackbd_getkeycode(unsigned int scancode) +{ + return -EINVAL; +} + +int mackbd_pretranslate(unsigned char scancode, char raw_mode) +{ + return 1; +} + +int mackbd_translate(unsigned char keycode, unsigned char *keycodep, + char raw_mode) +{ + if (!raw_mode) { + /* + * Convert R-shift/control/option to L version. + * Remap keycode 0 (A) to the unused keycode 0x5a. + * Other parts of the system assume 0 is not a valid keycode. + */ + switch (keycode) { + case 0x7b: keycode = 0x38; break; /* R-shift */ + case 0x7c: keycode = 0x3a; break; /* R-option */ + case 0x7d: keycode = 0x36; break; /* R-control */ + case 0: keycode = 0x5a; break; /* A */ + } + } + *keycodep = keycode; + return 1; +} + +int mackbd_unexpected_up(unsigned char keycode) +{ + return 0x80; +} + +static void +keyboard_input(unsigned char *data, int nb, struct pt_regs *regs) +{ + /* first check this is from register 0 */ + if (nb != 5 || (data[2] & 3) != KEYB_KEYREG) + return; /* ignore it */ + kbd_pt_regs = regs; + input_keycode(data[3], 0); + if (!(data[4] == 0xff || (data[4] == 0x7f && data[3] == 0x7f))) + input_keycode(data[4], 0); +} + +static void +input_keycode(int keycode, int repeat) +{ + struct kbd_struct *kbd; + int up_flag; + + kbd = kbd_table + fg_console; + up_flag = (keycode & 0x80); + keycode &= 0x7f; + if (!repeat) + del_timer(&repeat_timer); + + if (kbd->kbdmode != VC_RAW) { + if (!up_flag && !dont_repeat[keycode]) { + last_keycode = keycode; + repeat_timer.expires = jiffies + (repeat? HZ/15: HZ/2); + add_timer(&repeat_timer); + } + + /* + * XXX fix caps-lock behaviour by turning the key-up + * transition into a key-down transition. + */ + if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK)) + up_flag = 0; + } + + handle_scancode(keycode + up_flag); +} + +static void +kbd_repeat(unsigned long xxx) +{ + unsigned long flags; + + save_flags(flags); + cli(); + input_keycode(last_keycode, 1); + restore_flags(flags); +} + +static void +mouse_input(unsigned char *data, int nb, struct pt_regs *regs) +{ + /* [ACA:23-Mar-97] Three button mouse support. This is designed to + function with MkLinux DR-2.1 style X servers. It only works with + three-button mice that conform to Apple's multi-button mouse + protocol. */ + + /* + The X server for MkLinux DR2.1 uses the following unused keycodes to + read the mouse: + + 0x7e This indicates that the next two keycodes should be interpreted + as mouse information. The first following byte's high bit + represents the state of the left button. The lower seven bits + represent the x-axis acceleration. The lower seven bits of the + second byte represent y-axis acceleration. + + 0x3f The x server interprets this keycode as a middle button + release. + + 0xbf The x server interprets this keycode as a middle button + depress. + + 0x40 The x server interprets this keycode as a right button + release. + + 0xc0 The x server interprets this keycode as a right button + depress. + + NOTES: There should be a better way of handling mice in the X server. + The MOUSE_ESCAPE code (0x7e) should be followed by three bytes instead + of two. The three mouse buttons should then, in the X server, be read + as the high-bits of all three bytes. The x and y motions can still be + in the first two bytes. Maybe I'll do this... + */ + + /* + Handler 4 -- Apple Extended mouse protocol. + + For Apple's 3-button mouse protocol the data array will contain the + following values: + + BITS COMMENTS + data[0] = 0000 0000 ADB packet identifer. + data[1] = 0100 0000 Extended protocol register. + Bits 6-7 are the device id, which should be 1. + Bits 4-5 are resolution which is in "units/inch". + The Logitech MouseMan returns these bits clear but it has + 200/300cpi resolution. + Bits 0-3 are unique vendor id. + data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device. + Bits 2-3 should be 8 + 4. + Bits 4-7 should be 3 for a mouse device. + data[3] = bxxx xxxx Left button and x-axis motion. + data[4] = byyy yyyy Second button and y-axis motion. + data[5] = byyy bxxx Third button and fourth button. Y is additional + high bits of y-axis motion. XY is additional + high bits of x-axis motion. + + NOTE: data[0] and data[2] are confirmed by the parent function and + need not be checked here. + */ + + /* + Handler 1 -- 100cpi original Apple mouse protocol. + Handler 2 -- 200cpi original Apple mouse protocol. + + For Apple's standard one-button mouse protocol the data array will + contain the following values: + + BITS COMMENTS + data[0] = 0000 0000 ADB packet identifer. + data[1] = ???? ???? (?) + data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device. + data[3] = bxxx xxxx First button and x-axis motion. + data[4] = byyy yyyy Second button and y-axis motion. + + NOTE: data[0] is confirmed by the parent function and need not be + checked here. + */ + struct kbd_struct *kbd; + + kbd = kbd_table + fg_console; + + /* Only send mouse codes when keyboard is in raw mode. */ + if (kbd->kbdmode == VC_RAW) { + static unsigned char uch_ButtonStateSecond = 0; + unsigned char uchButtonSecond; + + /* Send first button, second button and movement. */ + put_queue( 0x7e ); + put_queue( data[3] ); + put_queue( data[4] ); + + /* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */ + + /* Store the button state. */ + uchButtonSecond = (data[4] & 0x80); + + /* Send second button. */ + if (uchButtonSecond != uch_ButtonStateSecond) { + put_queue( 0x3f | uchButtonSecond ); + uch_ButtonStateSecond = uchButtonSecond; + } + + /* Macintosh 3-button mouse (handler 4). */ + if ((nb == 6) && (data[1] & 0x40)) { + static unsigned char uch_ButtonStateThird = 0; + unsigned char uchButtonThird; + + /* Store the button state for speed. */ + uchButtonThird = (data[5] & 0x80); + + /* Send third button. */ + if (uchButtonThird != uch_ButtonStateThird) { + put_queue( 0x40 | uchButtonThird ); + uch_ButtonStateThird = uchButtonThird; + } + } + } +} + +/* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */ +static unsigned char mac_ledmap[8] = { + 0, /* none */ + 4, /* scroll lock */ + 1, /* num lock */ + 5, /* scroll + num lock */ + 2, /* caps lock */ + 6, /* caps + scroll lock */ + 3, /* caps + num lock */ + 7, /* caps + num + scroll lock */ +}; + +static struct cuda_request led_request; +static int leds_pending; + +void mackbd_leds(unsigned char leds) +{ + if (led_request.got_reply) { + cuda_request(&led_request, leds_done, 4, ADB_PACKET, + ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), + 0xff, ~mac_ledmap[leds]); + } else + leds_pending = leds | 0x100; +} + +static void leds_done(struct cuda_request *req) +{ + int leds; + + if (leds_pending) { + leds = leds_pending & 0xff; + leds_pending = 0; + mackbd_leds(leds); + } +} + +void mackbd_init_hw(void) +{ + struct cuda_request req; + + adb_register(ADB_KEYBOARD, keyboard_input); + adb_register(ADB_MOUSE, mouse_input); + + /* turn on ADB auto-polling in the CUDA */ + cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); + while (!req.got_reply) + cuda_poll(); + + /* turn off all leds */ + cuda_request(&req, NULL, 4, ADB_PACKET, + ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, 0xff); + while (!req.got_reply) + cuda_poll(); + + /* get the keyboard to send separate codes for + left and right shift, control, option keys. */ + cuda_request(&req, NULL, 4, ADB_PACKET, + ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3); + while (!req.got_reply) + cuda_poll(); + + led_request.got_reply = 1; + + /* Try to switch the mouse (id 3) to handler 4, for three-button + mode. (0x20 is Service Request Enable, 0x03 is Device ID). */ + cuda_request(&req, NULL, 4, ADB_PACKET, + ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 ); + while (!req.got_reply) + cuda_poll(); +} + diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mackeymap.c linux/drivers/macintosh/mackeymap.c --- v2.1.50/linux/drivers/macintosh/mackeymap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/mackeymap.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,262 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, + 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72, + 0xfb79, 0xfb74, 0xf031, 0xf032, 0xf033, 0xf034, 0xf036, 0xf035, + 0xf03d, 0xf039, 0xf037, 0xf02d, 0xf038, 0xf030, 0xf05d, 0xfb6f, + 0xfb75, 0xf05b, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf027, + 0xfb6b, 0xf03b, 0xf05c, 0xf02c, 0xf02f, 0xfb6e, 0xfb6d, 0xf02e, + 0xf009, 0xf020, 0xf060, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xfb61, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a, + 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf109, 0xf200, 0xf10b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117, + 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xfb53, 0xfb44, 0xfb46, 0xfb48, 0xfb47, 0xfb5a, 0xfb58, + 0xfb43, 0xfb56, 0xf200, 0xfb42, 0xfb51, 0xfb57, 0xfb45, 0xfb52, + 0xfb59, 0xfb54, 0xf021, 0xf040, 0xf023, 0xf024, 0xf05e, 0xf025, + 0xf02b, 0xf028, 0xf026, 0xf05f, 0xf02a, 0xf029, 0xf07d, 0xfb4f, + 0xfb55, 0xf07b, 0xfb49, 0xfb50, 0xf201, 0xfb4c, 0xfb4a, 0xf022, + 0xfb4b, 0xf03a, 0xf07c, 0xf03c, 0xf03f, 0xfb4e, 0xfb4d, 0xf03e, + 0xf009, 0xf020, 0xf07e, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xfb41, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf10e, 0xf10f, 0xf110, 0xf10c, 0xf111, 0xf112, 0xf200, 0xf10a, + 0xf200, 0xf10c, 0xf200, 0xf203, 0xf200, 0xf113, 0xf200, 0xf10b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf20b, 0xf116, 0xf10d, 0xf117, + 0xf10b, 0xf20a, 0xf10a, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xfb73, 0xf917, 0xf919, 0xfb68, 0xfb67, 0xfb7a, 0xfb78, + 0xf916, 0xfb76, 0xf200, 0xf915, 0xfb71, 0xfb77, 0xf918, 0xfb72, + 0xfb79, 0xfb74, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, + 0xf200, 0xf05d, 0xf07b, 0xf05c, 0xf05b, 0xf07d, 0xf07e, 0xfb6f, + 0xfb75, 0xf200, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf200, + 0xfb6b, 0xf200, 0xf200, 0xf200, 0xf200, 0xfb6e, 0xfb6d, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf90a, 0xf90b, 0xf90c, 0xf90d, 0xf90e, 0xf90f, + 0xf910, 0xf911, 0xf914, 0xf912, 0xf913, 0xf200, 0xf200, 0xf200, + 0xf510, 0xf511, 0xf512, 0xf50e, 0xf513, 0xf514, 0xf200, 0xf516, + 0xf200, 0xf10c, 0xf200, 0xf202, 0xf200, 0xf515, 0xf200, 0xf517, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf50f, 0xf117, + 0xf50d, 0xf119, 0xf50c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018, + 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012, + 0xf019, 0xf014, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01e, 0xf01d, + 0xf200, 0xf200, 0xf01f, 0xf01f, 0xf07f, 0xf200, 0xf01d, 0xf00f, + 0xf015, 0xf01b, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf007, + 0xf00b, 0xf200, 0xf01c, 0xf200, 0xf07f, 0xf00e, 0xf00d, 0xf20e, + 0xf200, 0xf000, 0xf000, 0xf008, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a, + 0xf200, 0xf10c, 0xf200, 0xf204, 0xf200, 0xf109, 0xf200, 0xf10b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117, + 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018, + 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012, + 0xf019, 0xf014, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, 0xf00f, + 0xf015, 0xf200, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf200, + 0xf00b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf00e, 0xf00d, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf200, 0xf117, + 0xf200, 0xf119, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf20c, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf873, 0xf864, 0xf866, 0xf868, 0xf867, 0xf87a, 0xf878, + 0xf863, 0xf876, 0xf200, 0xf862, 0xf871, 0xf877, 0xf865, 0xf872, + 0xf879, 0xf874, 0xf831, 0xf832, 0xf833, 0xf834, 0xf836, 0xf835, + 0xf83d, 0xf839, 0xf837, 0xf82d, 0xf838, 0xf830, 0xf85d, 0xf86f, + 0xf875, 0xf85b, 0xf869, 0xf870, 0xf80d, 0xf86c, 0xf86a, 0xf827, + 0xf86b, 0xf83b, 0xf85c, 0xf82c, 0xf82f, 0xf86e, 0xf86d, 0xf82e, + 0xf809, 0xf820, 0xf860, 0xf87f, 0xf200, 0xf81b, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf210, 0xf211, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf900, 0xf901, 0xf902, 0xf903, 0xf904, 0xf905, + 0xf906, 0xf907, 0xf861, 0xf908, 0xf909, 0xf200, 0xf200, 0xf200, + 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a, + 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf509, 0xf200, 0xf50b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117, + 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf813, 0xf804, 0xf806, 0xf808, 0xf807, 0xf81a, 0xf818, + 0xf803, 0xf816, 0xf200, 0xf802, 0xf811, 0xf817, 0xf805, 0xf812, + 0xf819, 0xf814, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80f, + 0xf815, 0xf200, 0xf809, 0xf810, 0xf201, 0xf80c, 0xf80a, 0xf200, + 0xf80b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80e, 0xf80d, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703, + 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200, + 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208, + 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200, + 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, + 0xf306, 0xf307, 0xf801, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200, + 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a, + 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf509, 0xf200, 0xf50b, + 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117, + 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/mackeymap.map linux/drivers/macintosh/mackeymap.map --- v2.1.50/linux/drivers/macintosh/mackeymap.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/mackeymap.map Sat Aug 16 09:53:08 1997 @@ -0,0 +1,346 @@ +# Kernel keymap for Macintoshes. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# We use the Command (pretzel) key as Alt, and the Option key as AltGr. +# +keycode 0x00 = +keycode 0x01 = s +keycode 0x02 = d + altgr keycode 0x02 = Hex_D +keycode 0x03 = f + altgr keycode 0x03 = Hex_F +keycode 0x04 = h +keycode 0x05 = g +keycode 0x06 = z +keycode 0x07 = x +keycode 0x08 = c + altgr keycode 0x08 = Hex_C +keycode 0x09 = v +keycode 0x0a = +keycode 0x0b = b + altgr keycode 0x0b = Hex_B +keycode 0x0c = q +keycode 0x0d = w +keycode 0x0e = e + altgr keycode 0x0e = Hex_E +keycode 0x0f = r +keycode 0x10 = y +keycode 0x11 = t +keycode 0x12 = one exclam + alt keycode 0x12 = Meta_one +keycode 0x13 = two at at + control keycode 0x13 = nul + shift control keycode 0x13 = nul + alt keycode 0x13 = Meta_two +keycode 0x14 = three numbersign + control keycode 0x14 = Escape + alt keycode 0x14 = Meta_three +keycode 0x15 = four dollar dollar + control keycode 0x15 = Control_backslash + alt keycode 0x15 = Meta_four +keycode 0x16 = six asciicircum + control keycode 0x16 = Control_asciicircum + alt keycode 0x16 = Meta_six +keycode 0x17 = five percent + control keycode 0x17 = Control_bracketright + alt keycode 0x17 = Meta_five +keycode 0x18 = equal plus + alt keycode 0x18 = Meta_equal +keycode 0x19 = nine parenleft bracketright + alt keycode 0x19 = Meta_nine +keycode 0x1a = seven ampersand braceleft + control keycode 0x1a = Control_underscore + alt keycode 0x1a = Meta_seven +keycode 0x1b = minus underscore backslash + control keycode 0x1b = Control_underscore + shift control keycode 0x1b = Control_underscore + alt keycode 0x1b = Meta_minus +keycode 0x1c = eight asterisk bracketleft + control keycode 0x1c = Delete + alt keycode 0x1c = Meta_eight +keycode 0x1d = zero parenright braceright + alt keycode 0x1d = Meta_zero +keycode 0x1e = bracketright braceright asciitilde + control keycode 0x1e = Control_bracketright + alt keycode 0x1e = Meta_bracketright +keycode 0x1f = o +keycode 0x20 = u +keycode 0x21 = bracketleft braceleft + control keycode 0x21 = Escape + alt keycode 0x21 = Meta_bracketleft +keycode 0x22 = i +keycode 0x23 = p +keycode 0x24 = Return + alt keycode 0x24 = Meta_Control_m +keycode 0x25 = l +keycode 0x26 = j +keycode 0x27 = apostrophe quotedbl + control keycode 0x27 = Control_g + alt keycode 0x27 = Meta_apostrophe +keycode 0x28 = k +keycode 0x29 = semicolon colon + alt keycode 0x29 = Meta_semicolon +keycode 0x2a = backslash bar + control keycode 0x2a = Control_backslash + alt keycode 0x2a = Meta_backslash +keycode 0x2b = comma less + alt keycode 0x2b = Meta_comma +keycode 0x2c = slash question + control keycode 0x2c = Delete + alt keycode 0x2c = Meta_slash +keycode 0x2d = n +keycode 0x2e = m +keycode 0x2f = period greater + control keycode 0x2f = Compose + alt keycode 0x2f = Meta_period +keycode 0x30 = Tab Tab + alt keycode 0x30 = Meta_Tab +keycode 0x31 = space space + control keycode 0x31 = nul + alt keycode 0x31 = Meta_space +keycode 0x32 = grave asciitilde + control keycode 0x32 = nul + alt keycode 0x32 = Meta_grave +keycode 0x33 = Delete Delete + control keycode 0x33 = BackSpace + alt keycode 0x33 = Meta_Delete +keycode 0x34 = +keycode 0x35 = Escape Escape + alt keycode 0x35 = Meta_Escape +keycode 0x36 = Control +keycode 0x37 = Alt +keycode 0x38 = Shift +keycode 0x39 = Caps_Lock +keycode 0x3a = AltGr +keycode 0x3b = Left + alt keycode 0x3b = Decr_Console +keycode 0x3c = Right + alt keycode 0x3c = Incr_Console +keycode 0x3d = Down +keycode 0x3e = Up +keycode 0x3f = +keycode 0x40 = +keycode 0x41 = KP_Period +keycode 0x42 = +keycode 0x43 = KP_Multiply +keycode 0x44 = +keycode 0x45 = KP_Add +keycode 0x46 = +keycode 0x47 = Num_Lock +# shift keycode 0x47 = Bare_Num_Lock +keycode 0x48 = +keycode 0x49 = +keycode 0x4a = +keycode 0x4b = KP_Divide +keycode 0x4c = KP_Enter +keycode 0x4d = +keycode 0x4e = KP_Subtract +keycode 0x4f = +keycode 0x50 = +keycode 0x51 = +#keycode 0x51 = KP_Equals +keycode 0x52 = KP_0 + alt keycode 0x52 = Ascii_0 + altgr keycode 0x52 = Hex_0 +keycode 0x53 = KP_1 + alt keycode 0x53 = Ascii_1 + altgr keycode 0x53 = Hex_1 +keycode 0x54 = KP_2 + alt keycode 0x54 = Ascii_2 + altgr keycode 0x54 = Hex_2 +keycode 0x55 = KP_3 + alt keycode 0x55 = Ascii_3 + altgr keycode 0x55 = Hex_3 +keycode 0x56 = KP_4 + alt keycode 0x56 = Ascii_4 + altgr keycode 0x56 = Hex_4 +keycode 0x57 = KP_5 + alt keycode 0x57 = Ascii_5 + altgr keycode 0x57 = Hex_5 +keycode 0x58 = KP_6 + alt keycode 0x58 = Ascii_6 + altgr keycode 0x58 = Hex_6 +keycode 0x59 = KP_7 + alt keycode 0x59 = Ascii_7 + altgr keycode 0x59 = Hex_7 +# keycode 0 (A) is remapped to here +keycode 0x5a = a + altgr keycode 0x00 = Hex_A +keycode 0x5b = KP_8 + alt keycode 0x5b = Ascii_8 + altgr keycode 0x5b = Hex_8 +keycode 0x5c = KP_9 + alt keycode 0x5c = Ascii_9 + altgr keycode 0x5c = Hex_9 +keycode 0x5d = +keycode 0x5e = +keycode 0x5f = +keycode 0x60 = F5 F15 Console_17 + control keycode 0x60 = F5 + alt keycode 0x60 = Console_5 + control alt keycode 0x60 = Console_5 +keycode 0x61 = F6 F16 Console_18 + control keycode 0x61 = F6 + alt keycode 0x61 = Console_6 + control alt keycode 0x61 = Console_6 +keycode 0x62 = F7 F17 Console_19 + control keycode 0x62 = F7 + alt keycode 0x62 = Console_7 + control alt keycode 0x62 = Console_7 +keycode 0x63 = F3 F13 Console_15 + control keycode 0x63 = F3 + alt keycode 0x63 = Console_3 + control alt keycode 0x63 = Console_3 +keycode 0x64 = F8 F18 Console_20 + control keycode 0x64 = F8 + alt keycode 0x64 = Console_8 + control alt keycode 0x64 = Console_8 +keycode 0x65 = F9 F19 Console_21 + control keycode 0x65 = F9 + alt keycode 0x65 = Console_9 + control alt keycode 0x65 = Console_9 +keycode 0x66 = +keycode 0x67 = F11 F11 Console_23 + control keycode 0x67 = F11 + alt keycode 0x67 = Console_11 + control alt keycode 0x67 = Console_11 +keycode 0x68 = +keycode 0x69 = F13 +keycode 0x6a = +keycode 0x6b = Scroll_Lock Show_Memory Show_Registers + control keycode 0x6b = Show_State + alt keycode 0x6b = Scroll_Lock +keycode 0x6c = +keycode 0x6d = F10 F20 Console_22 + control keycode 0x6d = F10 + alt keycode 0x6d = Console_10 + control alt keycode 0x6d = Console_10 +keycode 0x6e = +keycode 0x6f = F12 F12 Console_24 + control keycode 0x6f = F12 + alt keycode 0x6f = Console_12 + control alt keycode 0x6f = Console_12 +keycode 0x70 = +keycode 0x71 = Pause +keycode 0x72 = Insert +keycode 0x73 = Home +keycode 0x74 = Prior + shift keycode 0x74 = Scroll_Backward +keycode 0x75 = Remove +keycode 0x76 = F4 F14 Console_16 + control keycode 0x76 = F4 + alt keycode 0x76 = Console_4 + control alt keycode 0x76 = Console_4 +keycode 0x77 = End +keycode 0x78 = F2 F12 Console_14 + control keycode 0x78 = F2 + alt keycode 0x78 = Console_2 + control alt keycode 0x78 = Console_2 +keycode 0x79 = Next + shift keycode 0x79 = Scroll_Forward +keycode 0x7a = F1 F11 Console_13 + control keycode 0x7a = F1 + alt keycode 0x7a = Console_1 + control alt keycode 0x7a = Console_1 +keycode 0x7b = Shift +keycode 0x7c = AltGr +keycode 0x7d = Control +keycode 0x7e = +keycode 0x7f = +#keycode 0x7f = Power + control shift keycode 0x7f = Boot +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.1.50/linux/drivers/macintosh/macserial.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/macserial.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,1923 @@ +/* + * macserial.c: Serial port driver for Power Macintoshes. + * + * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "macserial.h" + +/* + * It would be nice to dynamically allocate everything that + * depends on NUM_SERIAL, so we could support any number of + * Z8530s, but for now... + */ +#define NUM_SERIAL 2 /* Max number of ZS chips supported */ +#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ + +/* On PowerMacs, the hardware takes care of the SCC recovery time, + but we need the eieio to make sure that the accesses occur + in the order we want. */ +#define RECOVERY_DELAY eieio() + +struct mac_zschannel *zs_kgdbchan; +struct mac_zschannel zs_channels[NUM_CHANNELS]; + +struct mac_serial zs_soft[NUM_CHANNELS]; +int zs_channels_found; +struct mac_serial *zs_chain; /* list of all channels */ + +struct tty_struct zs_ttys[NUM_CHANNELS]; +/** struct tty_struct *zs_constty; **/ + +/* Console hooks... */ +static int zs_cons_chan = 0; +struct mac_serial *zs_consinfo = 0; +struct mac_zschannel *zs_conschan; + +/* + * Initialization values for when a channel is used for + * kernel gdb support. + */ +static unsigned char kgdb_regs[16] = { + 0, 0, 0, /* write 0, 1, 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK | SB1), /* write 4 */ + (Tx8 | TxENAB | RTS), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (NV), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 1, 0, /* 38400 baud divisor, write 12 + 13 */ + (BRENABL), /* write 14 */ + (DCDIE) /* write 15 */ +}; + +#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */ + +DECLARE_TASK_QUEUE(tq_serial); + +struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* Debugging... DEBUG_INTR is bad to use when one of the zs + * lines is your console ;( + */ +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW + +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +static void probe_sccs(void); +static void change_speed(struct mac_serial *info); + +static struct tty_struct *serial_table[NUM_CHANNELS]; +static struct termios *serial_termios[NUM_CHANNELS]; +static struct termios *serial_termios_locked[NUM_CHANNELS]; + +#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[4096]; /* This is cheating */ +static struct semaphore tmp_buf_sem = MUTEX; + +static inline int serial_paranoia_check(struct mac_serial *info, + dev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%d, %d) in %s\n"; + static const char *badinfo = + "Warning: null mac_serial for (%d, %d) in %s\n"; + + if (!info) { + printk(badinfo, MAJOR(device), MINOR(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, MAJOR(device), MINOR(device), routine); + return 1; + } +#endif + return 0; +} + +/* + * 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, 0 }; + +/* + * Reading and writing Z8530 registers. + */ +static inline unsigned char read_zsreg(struct mac_zschannel *channel, + unsigned char reg) +{ + unsigned char retval; + + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + retval = *channel->control; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsreg(struct mac_zschannel *channel, + unsigned char reg, unsigned char value) +{ + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + *channel->control = value; + RECOVERY_DELAY; + return; +} + +static inline unsigned char read_zsdata(struct mac_zschannel *channel) +{ + unsigned char retval; + + retval = *channel->data; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsdata(struct mac_zschannel *channel, + unsigned char value) +{ + *channel->data = value; + RECOVERY_DELAY; + return; +} + +static inline void load_zsregs(struct mac_zschannel *channel, + unsigned char *regs) +{ + ZS_CLEARERR(channel); + ZS_CLEARFIFO(channel); + /* Load 'em up */ + write_zsreg(channel, R4, regs[R4]); + write_zsreg(channel, R10, regs[R10]); + write_zsreg(channel, R3, regs[R3] & ~RxENABLE); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R1, regs[R1]); + write_zsreg(channel, R9, regs[R9]); + write_zsreg(channel, R11, regs[R11]); + write_zsreg(channel, R12, regs[R12]); + write_zsreg(channel, R13, regs[R13]); + write_zsreg(channel, R14, regs[R14]); + write_zsreg(channel, R15, regs[R15]); + write_zsreg(channel, R3, regs[R3]); + write_zsreg(channel, R5, regs[R5]); + return; +} + +/* Sets or clears DTR/RTS on the requested line */ +static inline void zs_rtsdtr(struct mac_serial *ss, int set) +{ + if (set) + ss->curregs[5] |= (RTS | DTR); + else + ss->curregs[5] &= ~(RTS | DTR); + write_zsreg(ss->zs_channel, 5, ss->curregs[5]); + return; +} + +static inline void kgdb_chaninit(struct mac_serial *ss, int intson, int bps) +{ + int brg; + + if (intson) { + kgdb_regs[R1] = INT_ALL_Rx; + kgdb_regs[R9] |= MIE; + } else { + kgdb_regs[R1] = 0; + kgdb_regs[R9] &= ~MIE; + } + brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + kgdb_regs[R12] = brg; + kgdb_regs[R13] = brg >> 8; + load_zsregs(ss->zs_channel, kgdb_regs); +} + +/* Utility routines for the Zilog */ +static inline int get_zsbaud(struct mac_serial *ss) +{ + struct mac_zschannel *channel = ss->zs_channel; + int brg; + + if ((ss->curregs[R11] & TCBR) == 0) { + /* higher rates don't use the baud rate generator */ + return (ss->curregs[R4] & X32CLK)? ZS_CLOCK/32: ZS_CLOCK/16; + } + /* The baud rate is split up between two 8-bit registers in + * what is termed 'BRG time constant' format in my docs for + * the chip, it is a function of the clk rate the chip is + * receiving which happens to be constant. + */ + brg = (read_zsreg(channel, 13) << 8); + brg |= read_zsreg(channel, 12); + return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); +} + +/* On receive, this clears errors and the receiver interrupts */ +static inline void rs_recv_clear(struct mac_zschannel *zsc) +{ + write_zsreg(zsc, 0, ERR_RES); + write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(struct mac_serial *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +extern void breakpoint(void); /* For the KGDB frame character */ + +static _INLINE_ void receive_chars(struct mac_serial *info, + struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch, stat, flag; + + while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { + + stat = read_zsreg(info->zs_channel, R1); + ch = read_zsdata(info->zs_channel); + +#if 0 /* KGDB not yet supported */ + /* Look for kgdb 'stop' character, consult the gdb documentation + * for remote target debugging and arch/sparc/kernel/sparc-stub.c + * to see how all this works. + */ + if ((info->kgdb_channel) && (ch =='\003')) { + breakpoint(); + continue; + } +#endif + + if (!tty) + continue; + queue_task(&tty->flip.tqueue, &tq_timer); + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + static int flip_buf_ovf; + ++flip_buf_ovf; + continue; + } + tty->flip.count++; + { + static int flip_max_cnt; + if (flip_max_cnt < tty->flip.count) + flip_max_cnt = tty->flip.count; + } + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + } else if (stat & FRM_ERR) { + /* this error is not sticky */ + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + } else + flag = 0; + *tty->flip.flag_buf_ptr++ = flag; + *tty->flip.char_buf_ptr++ = ch; + } +} + +static void transmit_chars(struct mac_serial *info) +{ + if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) + return; + info->tx_active = 0; + + if (info->x_char) { + /* Send next char */ + write_zsdata(info->zs_channel, info->x_char); + info->x_char = 0; + info->tx_active = 1; + return; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { + write_zsreg(info->zs_channel, 0, RES_Tx_P); + return; + } + + /* Send char */ + write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + info->tx_active = 1; + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); +} + +static _INLINE_ void status_handle(struct mac_serial *info) +{ + unsigned char status; + + /* Get status from Read Register 0 */ + status = read_zsreg(info->zs_channel, 0); + + /* Check for DCD transitions */ + if (((status ^ info->read_reg_zero) & DCD) != 0 + && info->tty && !C_CLOCAL(info->tty)) { + if (status & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { + queue_task(&info->tqueue_hangup, &tq_scheduler); + } + } + + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + /* + * For some reason, on the Power Macintosh, + * it seems that the CTS bit is 1 when CTS is + * *negated* and 0 when it is asserted. + * The DCD bit doesn't seem to be inverted + * like this. + */ + if ((status & CTS) == 0) { + if (info->tx_stopped) { + info->tx_stopped = 0; + if (!info->tx_active) + transmit_chars(info); + } + } else { + info->tx_stopped = 1; + } + } + + /* Clear status condition... */ + write_zsreg(info->zs_channel, 0, RES_EXT_INT); + info->read_reg_zero = status; +} + +/* + * This is the serial driver's generic interrupt routine + */ +void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct mac_serial *info = (struct mac_serial *) dev_id; + unsigned char zs_intreg; + int shift; + + /* NOTE: The read register 3, which holds the irq status, + * does so for both channels on each chip. Although + * the status value itself must be read from the A + * channel and is only valid when read from channel A. + * Yes... broken hardware... + */ +#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) + + if (info->zs_chan_a == info->zs_channel) + shift = 3; /* Channel A */ + else + shift = 0; /* Channel B */ + + for (;;) { + zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; + if ((zs_intreg & CHAN_IRQMASK) == 0) + break; + + if (zs_intreg & CHBRxIP) + receive_chars(info, regs); + if (zs_intreg & CHBTxIP) + transmit_chars(info); + if (zs_intreg & CHBEXT) + status_handle(info); + } +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + +#if 0 + save_flags(flags); cli(); + if (info->curregs[5] & TxENAB) { + info->curregs[5] &= ~TxENAB; + info->pendregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + } + restore_flags(flags); +#endif +} + +static void rs_start(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); +#if 0 + if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { + info->curregs[5] |= TxENAB; + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + } +#else + if (info->xmit_cnt && info->xmit_buf && !info->tx_active) { + transmit_chars(info); + } +#endif + restore_flags(flags); +} + +/* + * 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 + * rs_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 rs_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 mac_serial *info = (struct mac_serial *) 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 routine is called from the scheduler tqueue when the interrupt + * routine has signalled that a hangup has occurred. The path of + * hangup processing is: + * + * serial interrupt routine -> (scheduler tqueue) -> + * do_serial_hangup() -> tty->hangup() -> rs_hangup() + * + */ +static void do_serial_hangup(void *private_) +{ + struct mac_serial *info = (struct mac_serial *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + tty_hangup(tty); +} + +static void rs_timer(void) +{ +} + +static int startup(struct mac_serial * info) +{ + unsigned long flags; + + if (info->flags & ZILOG_INITIALIZED) + return 0; + + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (!info->xmit_buf) + return -ENOMEM; + } + + save_flags(flags); cli(); + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttyS%d (irq %d)...", info->line, info->irq); +#endif + + /* + * Clear the receive FIFO. + */ + ZS_CLEARFIFO(info->zs_channel); + info->xmit_fifo_size = 1; + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing and interrupts + */ + info->curregs[1] = (info->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->pendregs[1] = info->curregs[1]; + info->curregs[3] |= (RxENABLE | Rx8); + info->pendregs[3] = info->curregs[3]; + info->curregs[5] |= (TxENAB | Tx8); + info->pendregs[5] = info->curregs[5]; + info->curregs[9] |= (NV | MIE); + info->pendregs[9] = info->curregs[9]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + write_zsreg(info->zs_channel, 9, info->curregs[9]); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * Set the speed of the serial port + */ + change_speed(info); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + + info->flags |= ZILOG_INITIALIZED; + restore_flags(flags); + return 0; +} + +/* + * 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 mac_serial * info) +{ + unsigned long flags; + + if (!(info->flags & ZILOG_INITIALIZED)) + return; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d (irq %d)....", info->line, + info->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + info->pendregs[1] = info->curregs[1] = 0; + write_zsreg(info->zs_channel, 1, 0); /* no interrupts */ + + info->curregs[3] &= ~RxENABLE; + info->pendregs[3] = info->curregs[3]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + + info->curregs[5] &= ~TxENAB; + if (!info->tty || C_HUPCL(info->tty)) + info->curregs[5] &= ~(DTR | RTS); + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ZILOG_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 mac_serial *info) +{ + unsigned short port; + unsigned cflag; + int i; + int brg; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + i = cflag & CBAUD; + + save_flags(flags); cli(); + info->zs_baud = baud_table[i]; + info->clk_divisor = 16; + + switch (info->zs_baud) { + case ZS_CLOCK/16: /* 230400 */ + info->curregs[4] = X16CLK; + info->curregs[11] = 0; + break; + case ZS_CLOCK/32: /* 115200 */ + info->curregs[4] = X32CLK; + info->curregs[11] = 0; + break; + default: + info->curregs[4] = X16CLK; + info->curregs[11] = TCBR | RCBR; + brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); + info->curregs[12] = (brg & 255); + info->curregs[13] = ((brg >> 8) & 255); + info->curregs[14] = BRENABL; + } + + /* byte size and parity */ + info->curregs[3] &= ~RxNBITS_MASK; + info->curregs[5] &= ~TxNBITS_MASK; + switch (cflag & CSIZE) { + case CS5: + info->curregs[3] |= Rx5; + info->curregs[5] |= Tx5; + break; + case CS6: + info->curregs[3] |= Rx6; + info->curregs[5] |= Tx6; + break; + case CS7: + info->curregs[3] |= Rx7; + info->curregs[5] |= Tx7; + break; + case CS8: + default: /* defaults to 8 bits */ + info->curregs[3] |= Rx8; + info->curregs[5] |= Tx8; + break; + } + info->pendregs[3] = info->curregs[3]; + info->pendregs[5] = info->curregs[5]; + + info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); + if (cflag & CSTOPB) { + info->curregs[4] |= SB2; + } else { + info->curregs[4] |= SB1; + } + if (cflag & PARENB) { + info->curregs[4] |= PAR_ENA; + } + if (!(cflag & PARODD)) { + info->curregs[4] |= PAR_EVEN; + } + info->pendregs[4] = info->curregs[4]; + + if (!(cflag & CLOCAL)) { + if (!(info->curregs[15] & DCDIE)) + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + info->curregs[15] |= DCDIE; + } else + info->curregs[15] &= ~DCDIE; + if (cflag & CRTSCTS) { + info->curregs[15] |= CTSIE; + if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + info->tx_stopped = 1; + } else { + info->curregs[15] &= ~CTSIE; + info->tx_stopped = 0; + } + info->pendregs[15] = info->curregs[15]; + + /* Load up the new values */ + load_zsregs(info->zs_channel, info->curregs); + + restore_flags(flags); +} + +/* This is for console output over ttya/ttyb */ +static void rs_put_char(char ch) +{ + struct mac_zschannel *chan = zs_conschan; + int loops = 0; + unsigned long flags; + + if(!chan) + return; + + save_flags(flags); cli(); + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + if (++loops >= 1000000) + break; + write_zsdata(chan, ch); + restore_flags(flags); +} + +/* These are for receiving and sending characters under the kgdb + * source level kernel debugger. + */ +void putDebugChar(char kgdb_char) +{ + struct mac_zschannel *chan = zs_kgdbchan; + + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(chan, kgdb_char); +} + +char getDebugChar(void) +{ + struct mac_zschannel *chan = zs_kgdbchan; + + while ((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + udelay(5); + return read_zsdata(chan); +} + +/* + * Fair output driver allows a process to speak. + */ +static void rs_fair_output(void) +{ + int left; /* Output no more than that */ + unsigned long flags; + struct mac_serial *info = zs_consinfo; + char c; + + if (info == 0) return; + if (info->xmit_buf == 0) return; + + save_flags(flags); cli(); + left = info->xmit_cnt; + while (left != 0) { + c = info->xmit_buf[info->xmit_tail]; + info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + restore_flags(flags); + + rs_put_char(c); + + save_flags(flags); cli(); + left = MIN(info->xmit_cnt, left-1); + } + + restore_flags(flags); + return; +} + +/* + * zs_console_print is registered for printk. + */ +static void zs_console_print(const char *p) +{ + char c; + + while ((c = *(p++)) != 0) { + if (c == '\n') + rs_put_char('\r'); + rs_put_char(c); + } + + /* Comment this if you want to have a strict interrupt-driven output */ + rs_fair_output(); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + save_flags(flags); cli(); + transmit_chars(info); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, total = 0; + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf) + return 0; + + save_flags(flags); + while (1) { + cli(); + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + if (from_user) { + down(&tmp_buf_sem); + copy_from_user(tmp_buf, buf, c); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + up(&tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + if (info->xmit_cnt && !tty->stopped && !info->tx_stopped + && !info->tx_active) + transmit_chars(info); + restore_flags(flags); + return total; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_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); +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + unsigned long flags; +#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, "rs_throttle")) + return; + + if (I_IXOFF(tty)) { + save_flags(flags); cli(); + info->x_char = STOP_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + restore_flags(flags); + } + + if (C_CRTSCTS(tty)) { + /* + * Here we want to turn off the RTS line. On Macintoshes, + * we only get the DTR line, which goes to both DTR and + * RTS on the modem. RTS doesn't go out to the serial + * port socket. So you should make sure your modem is + * set to ignore DTR if you're using CRTSCTS. + */ + save_flags(flags); cli(); + info->curregs[5] &= ~(DTR | RTS); + info->pendregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + restore_flags(flags); + } +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + unsigned long flags; +#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, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + save_flags(flags); cli(); + if (info->x_char) + info->x_char = 0; + else { + info->x_char = START_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + } + restore_flags(flags); + } + + if (C_CRTSCTS(tty)) { + /* Assert RTS and DTR lines */ + save_flags(flags); cli(); + info->curregs[5] |= DTR | RTS; + info->pendregs[5] |= DTR | RTS; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + restore_flags(flags); + } +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct mac_serial * 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.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); +} + +static int set_serial_info(struct mac_serial * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct mac_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + copy_from_user(&new_serial,new_info,sizeof(new_serial)); + old_info = *info; + + if (!suser()) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.type != info->type) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ZILOG_USR_MASK) != + (info->flags & ~ZILOG_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ZILOG_USR_MASK) | + (new_serial.flags & ZILOG_USR_MASK)); + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->flags = ((info->flags & ~ZILOG_FLAGS) | + (new_serial.flags & ZILOG_FLAGS)); + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + +check_and_exit: + retval = startup(info); + return retval; +} + +/* + * 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 mac_serial * info, unsigned int *value) +{ + unsigned char status; + + cli(); + status = read_zsreg(info->zs_channel, 0); + sti(); + put_user(status,value); + return 0; +} + +static int get_modem_info(struct mac_serial *info, unsigned int *value) +{ + unsigned char control, status; + unsigned int result; + + cli(); + control = info->curregs[5]; + status = read_zsreg(info->zs_channel, 0); + sti(); + result = ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status & DCD) ? TIOCM_CAR: 0) + | ((status & CTS) ? 0: TIOCM_CTS); + put_user(result,value); + return 0; +} + +static int set_modem_info(struct mac_serial *info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg, bits; + + error = verify_area(VERIFY_READ, value, sizeof(int)); + if (error) + return error; + get_user(arg, value); + bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); + cli(); + switch (cmd) { + case TIOCMBIS: + info->curregs[5] |= bits; + break; + case TIOCMBIC: + info->curregs[5] &= ~bits; + break; + case TIOCMSET: + info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits; + break; + default: + sti(); + return -EINVAL; + } + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + sti(); + return 0; +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break( struct mac_serial * info, int duration) +{ + if (!info->port) + return; + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + duration; + cli(); + info->curregs[5] |= SND_BRK; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + schedule(); + info->curregs[5] &= ~SND_BRK; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + sti(); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct mac_serial * info = (struct mac_serial *)tty->driver_data; + int retval; + + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + 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 (!arg) + send_break(info, HZ/4); /* 1/4 second */ + return 0; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + send_break(info, arg ? arg*(HZ/10) : HZ/4); + return 0; + case TIOCGSOFTCAR: + return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); + case TIOCSSOFTCAR: + error = get_user(arg, (int *) arg); + if (error) + return error; + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + return 0; + case TIOCMGET: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct mac_serial)); + if (error) + return error; + copy_from_user((struct mac_serial *) arg, + info, sizeof(struct mac_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct mac_serial *info = (struct mac_serial *)tty->driver_data; + int was_stopped; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + was_stopped = info->tx_stopped; + + change_speed(info); + + if (was_stopped && !info->tx_stopped) + rs_start(tty); +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. + * Wait for the last remaining data to be sent. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct mac_serial * info = (struct mac_serial *)tty->driver_data; + unsigned long flags; + unsigned long timeout; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_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("rs_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + restore_flags(flags); + return; + } + info->flags |= ZILOG_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ZILOG_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ZILOG_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 != ZILOG_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receiver and receive interrupts. + */ + /** if (!info->iscons) ... **/ + info->curregs[3] &= ~RxENABLE; + info->pendregs[3] = info->curregs[3]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + info->curregs[1] &= ~(0x18); /* disable any rx ints */ + info->pendregs[1] = info->curregs[1]; + write_zsreg(info->zs_channel, 1, info->curregs[1]); + ZS_CLEARFIFO(info->zs_channel); + if (info->flags & ZILOG_INITIALIZED) { + /* + * Before we drop DTR, make sure the SCC transmitter + * has completely drained. + */ + timeout = jiffies+HZ; + while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + info->timeout; + schedule(); + if (jiffies > timeout) + break; + } + } + + 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 (tty->ldisc.num != ldiscs[N_TTY].num) { + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (tty->ldisc.open) + (tty->ldisc.open)(tty); + } + 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 &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE| + ZILOG_CLOSING); + wake_up_interruptible(&info->close_wait); + restore_flags(flags); +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void rs_hangup(struct tty_struct *tty) +{ + struct mac_serial * info = (struct mac_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct mac_serial *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 (info->flags & ZILOG_CLOSING) { + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + if (info->flags & ZILOG_HUP_NOTIFY) + return -EAGAIN; + else + return -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 & ZILOG_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ZILOG_CALLOUT_ACTIVE) && + (info->flags & ZILOG_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ZILOG_CALLOUT_ACTIVE) && + (info->flags & ZILOG_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ZILOG_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 & ZILOG_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ZILOG_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 + * rs_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 & ZILOG_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) + zs_rtsdtr(info, 1); + sti(); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ZILOG_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ZILOG_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && + !(info->flags & ZILOG_CLOSING) && + (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD))) + break; + if (current->signal & ~current->blocked) { + 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 |= ZILOG_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its ZILOG structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct mac_serial *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= zs_channels_found)) + return -ENODEV; + info = zs_soft + line; + + /* Is the kgdb running over this line? */ + if (info->kgdb_channel) + return -ENODEV; + if (serial_paranoia_check(info, tty->device, "rs_open")) + return -ENODEV; +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->count); +#endif + + info->count++; + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open returning after block_til_ready with %d\n", + retval); +#endif + return retval; + } + + if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* Finally, routines used to initialize the serial driver. */ + +static void show_serial_version(void) +{ + printk("PowerMac Z8530 serial driver version 1.00\n"); +} + +/* Ask the PROM how many Z8530s we have and initialize their zs_channels */ +static void +probe_sccs() +{ + struct device_node *dev, *ch; + struct mac_serial **pp; + int n; + + n = 0; + pp = &zs_chain; + for (dev = find_devices("escc"); dev != 0; dev = dev->next) { + if (n >= NUM_CHANNELS) { + printk("Sorry, can't use %s: no more channels\n", + dev->full_name); + continue; + } + for (ch = dev->child; ch != 0; ch = ch->sibling) { + if (ch->n_addrs < 1 || ch ->n_intrs < 1) { + printk("Can't use %s: %d addrs %d intrs\n", + ch->full_name, ch->n_addrs, ch->n_intrs); + continue; + } + zs_channels[n].control = (volatile unsigned char *) + ch->addrs[0].address; + zs_channels[n].data = zs_channels[n].control + + ch->addrs[0].size / 2; + zs_soft[n].zs_channel = &zs_channels[n]; + zs_soft[n].irq = ch->intrs[0]; + if (request_irq(ch->intrs[0], rs_interrupt, 0, + "SCC", &zs_soft[n])) + panic("macserial: can't get irq %d", + ch->intrs[0]); + /* XXX this assumes the prom puts chan A before B */ + if (n & 1) + zs_soft[n].zs_chan_a = &zs_channels[n-1]; + else + zs_soft[n].zs_chan_a = &zs_channels[n]; + + *pp = &zs_soft[n]; + pp = &zs_soft[n].zs_next; + ++n; + } + } + *pp = 0; + zs_channels_found = n; +} + +/* rs_init inits the driver */ +int rs_init(void) +{ + int channel, i; + unsigned long flags; + struct mac_serial *info; + + /* Setup base handler, and timer table. */ + init_bh(SERIAL_BH, do_serial_bh); + timer_table[RS_TIMER].fn = rs_timer; + timer_table[RS_TIMER].expires = 0; + + /* Find out how many Z8530 SCCs we have */ + if (zs_chain == 0) + probe_sccs(); + + show_serial_version(); + + /* Initialize the tty_driver structure */ + /* Not all of this is exactly right for us. */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = zs_channels_found; + 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 = + B38400 | 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 = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + + /* + * 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; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + save_flags(flags); cli(); + + for (channel = 0; channel < zs_channels_found; ++channel) { + zs_soft[channel].clk_divisor = 16; + zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); + + /* If console serial line, then enable interrupts. */ + if (zs_soft[channel].is_cons) { + write_zsreg(zs_soft[channel].zs_channel, R1, + (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); + write_zsreg(zs_soft[channel].zs_channel, R9, + (NV | MIE)); + } + /* If this is the kgdb line, enable interrupts because we + * now want to receive the 'control-c' character from the + * client attached to us asynchronously. + */ + if (zs_soft[channel].kgdb_channel) + kgdb_chaninit(&zs_soft[channel], 1, + zs_soft[channel].zs_baud); + } + + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) + { + info->magic = SERIAL_MAGIC; + info->port = (int) info->zs_channel->control; + info->line = i; + info->tty = 0; + info->custom_divisor = 16; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->tqueue_hangup.routine = do_serial_hangup; + info->tqueue_hangup.data = info; + info->callout_termios =callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + printk("tty%02d at 0x%08x (irq = %d)", info->line, + info->port, info->irq); + printk(" is a Z8530 ESCC\n"); + } + + restore_flags(flags); + + return 0; +} + +/* + * register_serial and unregister_serial allows for serial ports to be + * configured at run-time, to support PCMCIA modems. + */ +/* PowerMac: Unused at this time, just here to make things link. */ +int register_serial(struct serial_struct *req) +{ + return -1; +} + +void unregister_serial(int line) +{ + return; +} + +extern void register_console(void (*proc)(const char *)); + +/* + * Initialization values for when a channel is used for + * a serial console. + */ +static unsigned char cons_init_regs[16] = { + 0, 0, 0, /* write 0, 1, 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK | SB1), /* write 4 */ + (Tx8 | TxENAB | RTS), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + 0, /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 1, 0, /* 38400 baud divisor, write 12 + 13 */ + (BRENABL), /* write 14 */ + 0 /* write 15 */ +}; + +/* + * Hooks for running a serial console. con_init() calls this if the + * console is being run over one of the serial ports. + * 'channel' is decoded as 1=modem, 2=printer. + */ +void +rs_cons_hook(int chip, int out, int channel) +{ + int brg; + + if (!out) + return; + if (zs_consinfo != 0) { + printk("rs_cons_hook called twice?\n"); + return; + } + if (zs_chain == 0) + probe_sccs(); + --channel; + if (channel < 0 || channel >= zs_channels_found) { + printk("rs_cons_hook: channel = %d?\n", channel); + return; + } + + zs_cons_chan = channel; + zs_consinfo = &zs_soft[channel]; + zs_conschan = zs_consinfo->zs_channel; + zs_consinfo->clk_divisor = 16; + zs_consinfo->zs_baud = 38400; + zs_consinfo->is_cons = 1; + + memcpy(zs_consinfo->curregs, cons_init_regs, sizeof(cons_init_regs)); + brg = BPS_TO_BRG(zs_consinfo->zs_baud, ZS_CLOCK/16); + zs_consinfo->curregs[R12] = brg; + zs_consinfo->curregs[R13] = brg >> 8; + load_zsregs(zs_conschan, zs_consinfo->curregs); + + register_console(zs_console_print); + printk("zs%d: console I/O\n", channel); +} + +/* This is called at boot time to prime the kgdb serial debugging + * serial line. The 'tty_num' argument is 0 for /dev/ttyS0 and 1 + * for /dev/ttyS1 which is determined in setup_arch() from the + * boot command line flags. + */ +void +rs_kgdb_hook(int tty_num) +{ + if (zs_chain == 0) + probe_sccs(); + zs_kgdbchan = zs_soft[tty_num].zs_channel; + zs_soft[tty_num].clk_divisor = 16; + zs_soft[tty_num].zs_baud = get_zsbaud(&zs_soft[tty_num]); + zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ + zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */ + /* Turn on transmitter/receiver at 8-bits/char */ + kgdb_chaninit(&zs_soft[tty_num], 0, 9600); + ZS_CLEARERR(zs_kgdbchan); + ZS_CLEARFIFO(zs_kgdbchan); +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/macserial.h linux/drivers/macintosh/macserial.h --- v2.1.50/linux/drivers/macintosh/macserial.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/macserial.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,407 @@ +/* + * macserial.h: Definitions for the Macintosh Z8530 serial driver. + * + * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _MACSERIAL_H +#define _MACSERIAL_H + +#define NUM_ZSREGS 16 + +struct serial_struct { + int type; + int line; + int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char reserved_char[2]; + int hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + int reserved[4]; +}; + +/* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ZILOG_CLOSING_WAIT_INF 0 +#define ZILOG_CLOSING_WAIT_NONE 65535 + +/* + * Definitions for ZILOG_struct (and serial_struct) flags field + */ +#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + on the callout port */ +#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ +#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define ZILOG_SPD_MASK 0x0030 +#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ +#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ +#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +struct mac_zschannel { + volatile unsigned char *control; + volatile unsigned char *data; +}; + +struct mac_serial { + struct mac_serial *zs_next; /* For IRQ servicing chain */ + struct mac_zschannel *zs_channel; /* Channel registers */ + struct mac_zschannel *zs_chan_a; /* A side registers */ + unsigned char read_reg_zero; + + char soft_carrier; /* Use soft carrier on this channel */ + char break_abort; /* Is serial console in, so process brk/abrt */ + char kgdb_channel; /* Kgdb is running on this channel */ + char is_cons; /* Is this our console. */ + unsigned char tx_active; /* character is being xmitted */ + unsigned char tx_stopped; /* output is suspended */ + + /* We need to know the current clock divisor + * to read the bps rate the chip has currently + * loaded. + */ + unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ + int zs_baud; + + /* Current write register values */ + unsigned char curregs[NUM_ZSREGS]; + + /* Values we need to set next opportunity */ + unsigned char pendregs[NUM_ZSREGS]; + + char change_needed; + + int magic; + int baud_base; + int port; + int irq; + int flags; /* defined in tty.h */ + int type; /* UART type */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int count; /* # of fd on device */ + 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 tq_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; +}; + + +#define SERIAL_MAGIC 0x5301 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#define SERIAL_XMIT_SIZE 4096 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +/* The Zilog register set */ + +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENABLE 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ +#define RxNBITS_MASK 0xc0 + +/* Write Register 4 */ + +#define PAR_ENA 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ +#define SB_MASK 0xc + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ +#define XCLK_MASK 0xC0 + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define TxNBITS_MASK 0x60 +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENABL 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define ZCIE 2 /* Zero count IE */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define FRM_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ + +/* Misc macros */ +#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) +#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + } while(0) + +#endif /* !(_MACSERIAL_H) */ diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- v2.1.50/linux/drivers/macintosh/nvram.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/nvram.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,87 @@ +/* + * /dev/nvram driver for Power Macintosh. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define NVRAM_SIZE 8192 + +static long long nvram_llseek(struct inode *inode, struct file *file, + loff_t offset, int origin) +{ + switch (origin) { + case 1: + offset += file->f_pos; + break; + case 2: + offset += NVRAM_SIZE; + break; + } + if (offset < 0) + return -EINVAL; + file->f_pos = offset; + return file->f_pos; +} + +static long read_nvram(struct inode *inode, struct file *file, + char *buf, unsigned long count) +{ + unsigned int i = file->f_pos; + char *p = buf; + + for (; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) + put_user(nvram_read_byte(i), p); + file->f_pos = i; + return p - buf; +} + +static long write_nvram(struct inode *inode, struct file *file, + const char *buf, unsigned long count) +{ + unsigned int i = file->f_pos; + const char *p = buf; + char c; + + for (; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) { + get_user(c, p); + nvram_write_byte(i, c); + } + file->f_pos = i; + return p - buf; +} + +static int nvram_open(struct inode *inode, struct file *file) +{ + return 0; +} + +struct file_operations nvram_fops = { + nvram_llseek, + read_nvram, + write_nvram, + NULL, /* nvram_readdir */ + NULL, /* nvram_select */ + NULL, /* nvram_ioctl */ + NULL, /* nvram_mmap */ + nvram_open, + NULL, /* no special release code */ + NULL /* fsync */ +}; + +static struct miscdevice nvram_dev = { + NVRAM_MINOR, + "nvram", + &nvram_fops +}; + +__initfunc(int nvram_init(void)) +{ + misc_register(&nvram_dev); + return 0; +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/platinum.c linux/drivers/macintosh/platinum.c --- v2.1.50/linux/drivers/macintosh/platinum.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/platinum.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,623 @@ +/* + * platinum.c: Console support for PowerMac "platinum" display adaptor. + * + * Copyright (C) 1996 Paul Mackerras and Mark Abene. + * + * 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 +#include +#include "pmac-cons.h" +#include "platinum.h" + +/* + * Structure of the registers for the DACula colormap device. + */ +struct cmap_regs { + unsigned char addr; + char pad1[15]; + unsigned char d1; + char pad2[15]; + unsigned char d2; + char pad3[15]; + unsigned char lut; + char pad4[15]; +}; + +/* + * Structure of the registers for the "platinum" display adaptor". + */ +#define PAD(x) char x[12] + +struct preg { /* padded register */ + unsigned r; + char pad[12]; +}; + +struct platinum_regs { + struct preg reg[128]; +}; + +static void set_platinum_clock(unsigned char *clksel); +static int read_platinum_sense(void); +static int platinum_vram_reqd(int vmode, int cmode); + +static int total_vram; /* total amount of video memory, bytes */ +static unsigned char *frame_buffer; +static unsigned char *base_frame_buffer; +static struct cmap_regs *cmap_regs; +static volatile struct platinum_regs *plat_regs; + +/* + * Register initialization tables for the platinum display. + * + * It seems that there are two different types of platinum display + * out there. Older ones use the values in clocksel[1], for which + * the formula for the clock frequency seems to be + * F = 14.3MHz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5)) + * Newer ones use the values in clocksel[0], for which the formula + * seems to be + * F = 15MHz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5)) + */ +struct plat_regvals { + int fb_offset; + int pitch[3]; + unsigned regs[26]; + unsigned char plat_offset[3]; + unsigned char mode[3]; + unsigned char dacula_ctrl[3]; + unsigned char clocksel[2][2]; +}; + +#define DIV2 0x20 +#define DIV4 0x40 +#define DIV8 0x60 +#define DIV16 0x80 + +/* 1280x1024, 75Hz (20) */ +static struct plat_regvals platinum_reg_init_20 = { + 0x5c00, + { 1312, 2592, 2592 }, + { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, + 0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d, + 0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50, + 0x850, 0x851 }, { 0x58, 0x5d, 0x5d }, + { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, + {{ 45, 3 }, { 66, 7 }} +}; + +/* 1280x960, 75Hz (19) */ +static struct plat_regvals platinum_reg_init_19 = { + 0x5c00, + { 1312, 2592, 2592 }, + { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, + 0, 0xb2, 0xd2, 0x12, 0x1a3, 0x23, 0x28, 0x2d, + 0x5c, 0x19c, 0x1a2, 0x7d0, 0x7ce, 4, 9, 0x4c, + 0x7cc, 0x7cd }, { 0x56, 0x5b, 0x5b }, + { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, + {{ 42, 3 }, { 44, 5 }} +}; + +/* 1152x870, 75Hz (18) */ +static struct plat_regvals platinum_reg_init_18 = { + 0x11b0, + { 1184, 2336, 4640 }, + { 0xff0, 4, 0, 0, 0, 0, 0x38f, 0, + 0, 0x294, 0x16c, 0x20, 0x2d7, 0x3f, 0x49, 0x53, + 0x82, 0x2c2, 0x2d6, 0x726, 0x724, 4, 9, 0x52, + 0x71e, 0x722 }, { 0x74, 0x7c, 0x81 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV2 }, { 42, 6 }} +}; + +/* 1024x768, 75Hz (17) */ +static struct plat_regvals platinum_reg_init_17 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x254, 0x14b, 0x18, 0x295, 0x2f, 0x32, 0x3b, + 0x80, 0x280, 0x296, 0x648, 0x646, 4, 9, 0x40, + 0x640, 0x644 }, { 0x72, 0x7a, 0x7f }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV2 }, { 67, 12 }} +}; + +/* 1024x768, 75Hz (16) */ +static struct plat_regvals platinum_reg_init_16 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x250, 0x147, 0x17, 0x28f, 0x2f, 0x35, 0x47, + 0x82, 0x282, 0x28e, 0x640, 0x63e, 4, 9, 0x3c, + 0x63c, 0x63d }, { 0x74, 0x7c, 0x81 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 20, 0 + DIV2 }, { 11, 2 }} +}; + +/* 1024x768, 70Hz (15) */ +static struct plat_regvals platinum_reg_init_15 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x254, 0x14b, 0x22, 0x297, 0x43, 0x49, 0x5b, + 0x86, 0x286, 0x296, 0x64c, 0x64a, 0xa, 0xf, 0x44, + 0x644, 0x646 }, { 0x78, 0x80, 0x85 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 19, 0 + DIV2 }, { 110, 21 }} +}; + +/* 1024x768, 60Hz (14) */ +static struct plat_regvals platinum_reg_init_14 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b, + 0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44, + 0x644, 0x646 }, { 0x80, 0x88, 0x8d }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }} +}; + +/* 832x624, 75Hz (13) */ +static struct plat_regvals platinum_reg_init_13 = { + 0x70, + { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */ + { 0xff0, 4, 0, 0, 0, 0, 0x299, 0, + 0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37, + 0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52, + 0x532, 0x533 }, { 0x7c, 0x84, 0x89 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }} +}; + +/* 800x600, 75Hz (12) */ +static struct plat_regvals platinum_reg_init_12 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39, + 0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e, + 0x4de, 0x4df }, { 0x64, 0x6c, 0x71 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }} +}; + +/* 800x600, 72Hz (11) */ +static struct plat_regvals platinum_reg_init_11 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ca, 0x104, 0x1e, 0x207, 0x3b, 0x44, 0x4d, + 0x56, 0x1e6, 0x206, 0x534, 0x532, 0xa, 0xe, 0x38, + 0x4e8, 0x4ec }, { 0x48, 0x50, 0x55 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV4 }, { 42, 6 + DIV2 }} +}; + +/* 800x600, 60Hz (10) */ +static struct plat_regvals platinum_reg_init_10 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d, + 0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34, + 0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV4 }, { 95, 1 + DIV8 }} +}; + +/* 800x600, 56Hz (9) --unsupported? copy of mode 10 for now... */ +static struct plat_regvals platinum_reg_init_9 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d, + 0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34, + 0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV4 }, { 88, 1 + DIV8 }} +}; + +/* 768x576, 50Hz Interlaced-PAL (8) */ +static struct plat_regvals platinum_reg_init_8 = { + 0x1010, + { 800, 1568, 3104 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36, + 0x47, 0x1c7, 0x1d6, 0x271, 0x270, 4, 9, 0x27, + 0x267, 0x26b }, { 0x39, 0x41, 0x46 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }} +}; + +/* 640x870, 75Hz Portrait (7) */ +static struct plat_regvals platinum_reg_init_7 = { + 0xb10, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x176, 0xd0, 0x14, 0x19f, 0x27, 0x2d, 0x3f, + 0x4a, 0x18a, 0x19e, 0x72c, 0x72a, 4, 9, 0x58, + 0x724, 0x72a }, { 0x3c, 0x44, 0x49 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }} +}; + +/* 640x480, 67Hz (6) */ +static struct plat_regvals platinum_reg_init_6 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x209, 0, + 0, 0x18e, 0xd8, 0x10, 0x1af, 0x1f, 0x25, 0x37, + 0x4a, 0x18a, 0x1ae, 0x41a, 0x418, 4, 9, 0x52, + 0x412, 0x416 }, { 0x3c, 0x44, 0x49 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 99, 4 + DIV8 }, { 42, 5 + DIV4 }} +}; + +/* 640x480, 60Hz (5) */ +static struct plat_regvals platinum_reg_init_5 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e, + 0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44, + 0x404, 0x408 }, { 0x34, 0x3c, 0x41 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }} +}; + +/* 640x480, 60Hz Interlaced-NTSC (4) */ +static struct plat_regvals platinum_reg_init_4 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30, + 0x37, 0x177, 0x184, 0x20d, 0x20c, 5, 0xb, 0x23, + 0x203, 0x206 }, { 0x29, 0x31, 0x36 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }} +}; + +/* 640x480, 50Hz Interlaced-PAL (3) */ +static struct plat_regvals platinum_reg_init_3 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36, + 0x67, 0x1a7, 0x1d6, 0x271, 0x270, 4, 9, 0x57, + 0x237, 0x26b }, { 0x59, 0x61, 0x66 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }} +}; + +/* 512x384, 60Hz (2) */ +static struct plat_regvals platinum_reg_init_2 = { + 0x1010, + { 544, 1056, 2080 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x25c, 0x140, 0x10, 0x27f, 0x1f, 0x2b, 0x4f, + 0x68, 0x268, 0x27e, 0x32e, 0x32c, 4, 9, 0x2a, + 0x32a, 0x32b }, { 0x5a, 0x62, 0x67 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 33, 2 + DIV8 }, { 79, 9 + DIV8 }} +}; + +/* 512x384, 60Hz Interlaced-NTSC (1) */ +static struct plat_regvals platinum_reg_init_1 = { + 0x1010, + { 544, 1056, 2080 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30, + 0x57, 0x157, 0x184, 0x20d, 0x20c, 5, 0xb, 0x53, + 0x1d3, 0x206 }, { 0x49, 0x51, 0x56 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }} +}; + +static struct plat_regvals *platinum_reg_init[VMODE_MAX] = { + &platinum_reg_init_1, + &platinum_reg_init_2, + &platinum_reg_init_3, + &platinum_reg_init_4, + &platinum_reg_init_5, + &platinum_reg_init_6, + &platinum_reg_init_7, + &platinum_reg_init_8, + &platinum_reg_init_9, + &platinum_reg_init_10, + &platinum_reg_init_11, + &platinum_reg_init_12, + &platinum_reg_init_13, + &platinum_reg_init_14, + &platinum_reg_init_15, + &platinum_reg_init_16, + &platinum_reg_init_17, + &platinum_reg_init_18, + &platinum_reg_init_19, + &platinum_reg_init_20 +}; + +/* + * Get the monitor sense value. + */ +static int +read_platinum_sense() +{ + int sense; + + plat_regs->reg[23].r = 7; /* turn off drivers */ + eieio(); __delay(2000); + sense = (~plat_regs->reg[23].r & 7) << 8; + + /* drive each sense line low in turn and collect the other 2 */ + plat_regs->reg[23].r = 3; /* drive A low */ + eieio(); __delay(2000); + sense |= (~plat_regs->reg[23].r & 3) << 4; + eieio(); + plat_regs->reg[23].r = 5; /* drive B low */ + eieio(); __delay(2000); + sense |= (~plat_regs->reg[23].r & 4) << 1; + sense |= (~plat_regs->reg[23].r & 1) << 2; + eieio(); + plat_regs->reg[23].r = 6; /* drive C low */ + eieio(); __delay(2000); + sense |= (~plat_regs->reg[23].r & 6) >> 1; + eieio(); + + plat_regs->reg[23].r = 7; /* turn off drivers */ + return sense; +} + +static inline int platinum_vram_reqd(int vmode, int cmode) +{ + return vmode_attrs[vmode-1].vres + * platinum_reg_init[vmode-1]->pitch[cmode]; +} + +void +map_platinum(struct device_node *dp) +{ + int i, sense; + unsigned long addr, size; + int bank0, bank1, bank2, bank3; + + if (dp->next != 0) + printk("Warning: only using first platinum display device\n"); + if (dp->n_addrs != 2) + panic("expecting 2 addresses for platinum (got %d)", + dp->n_addrs); + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x400000) { + /* frame buffer - map only 4MB */ + frame_buffer = ioremap(addr, 0x400000); + base_frame_buffer = frame_buffer; + } else { + /* registers */ + plat_regs = ioremap(addr, size); + } + } + cmap_regs = ioremap(0xf301b000, 0x1000); /* XXX not in prom? */ + + /* Grok total video ram */ + plat_regs->reg[16].r = (unsigned)frame_buffer; + plat_regs->reg[20].r = 0x1011; /* select max vram */ + plat_regs->reg[24].r = 0; /* switch in vram */ + eieio(); + frame_buffer[0x100000] = 0x34; + frame_buffer[0x200000] = 0x56; + frame_buffer[0x300000] = 0x78; + eieio(); + bank0 = 1; /* builtin 1MB vram, always there */ + bank1 = frame_buffer[0x100000] == 0x34; + bank2 = frame_buffer[0x200000] == 0x56; + bank3 = frame_buffer[0x300000] == 0x78; + total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000; + printk("Total VRAM = %dMB\n", total_vram / 1024 / 1024); + + sense = read_platinum_sense(); + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || platinum_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (platinum_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_60; + printk("Monitor sense value = 0x%x, ", sense); + + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_32) + color_mode = CMODE_8; + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + while (color_mode > CMODE_8 + && platinum_vram_reqd(video_mode, color_mode) > total_vram) + --color_mode; + /* + * Reduce the video mode if we don't have enough VRAM. + */ + while (platinum_vram_reqd(video_mode, color_mode) > total_vram) + --video_mode; +} + +#define STORE_D2(a, v) { \ + out_8(&cmap_regs->addr, (a+32)); \ + out_8(&cmap_regs->d2, (v)); \ +} + +static void +set_platinum_clock(unsigned char *clksel) +{ + STORE_D2(6, 0xc6); + out_8(&cmap_regs->addr, 3+32); + if (cmap_regs->d2 == 2) { + STORE_D2(7, clksel[0]); + STORE_D2(8, clksel[1]); + STORE_D2(3, 3); + } else { + STORE_D2(4, clksel[0]); + STORE_D2(5, clksel[1]); + STORE_D2(3, 2); + } + __delay(5000); + STORE_D2(9, 0xa6); +} + +void +platinum_init() +{ + int i, yoff, width, clkmode, dtype; + struct plat_regvals *init; + unsigned *p; + int one_mb = 0; + + if (total_vram == 0x100000) one_mb=1; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = platinum_reg_init[video_mode-1]) == 0) + panic("platinum: video mode %d not supported", video_mode); + + frame_buffer = base_frame_buffer + init->fb_offset; + /* printk("Frame buffer start address is %p\n", frame_buffer); */ + + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + width = vmode_attrs[video_mode-1].hres; + n_scanlines = vmode_attrs[video_mode-1].vres; + row_pitch = line_pitch * 16; + + /* Initialize display timing registers */ + out_be32(&plat_regs->reg[24].r, 7); /* turn display off */ + + for (i = 0; i < 26; ++i) + plat_regs->reg[i+32].r = init->regs[i]; + plat_regs->reg[26+32].r = (one_mb ? init->plat_offset[color_mode] + 4 - color_mode : init->plat_offset[color_mode]); + plat_regs->reg[16].r = (unsigned) frame_buffer; + plat_regs->reg[18].r = line_pitch; + plat_regs->reg[19].r = (one_mb ? init->mode[color_mode+1] : init->mode[color_mode]); + plat_regs->reg[20].r = (one_mb ? 0x11 : 0x1011); + plat_regs->reg[21].r = 0x100; + plat_regs->reg[22].r = 1; + plat_regs->reg[23].r = 1; + plat_regs->reg[26].r = 0xc00; + plat_regs->reg[27].r = 0x235; + /* plat_regs->reg[27].r = 0x2aa; */ + + STORE_D2(0, (one_mb ? init->dacula_ctrl[color_mode] & 0xf : init->dacula_ctrl[color_mode])); + STORE_D2(1, 4); + STORE_D2(2, 0); + /* + * Try to determine whether we have an old or a new DACula. + */ + out_8(&cmap_regs->addr, 0x40); + dtype = cmap_regs->d2; + switch (dtype) { + case 0x3c: + clkmode = 1; + break; + case 0x84: + clkmode = 0; + break; + default: + clkmode = 0; + printk("Unknown DACula type: %x\n", cmap_regs->d2); + } + set_platinum_clock(init->clocksel[clkmode]); + + out_be32(&plat_regs->reg[24].r, 0); /* turn display on */ + + pmac_init_palette(); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + 0x10; + + /* Clear screen */ + p = (unsigned *) (frame_buffer + 0x10); + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = width; + display_info.depth = 8 * pixel_size; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "platinum", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + 0x10; + display_info.cmap_adr_address = (unsigned long) &cmap_regs->addr; + display_info.cmap_data_address = (unsigned long) &cmap_regs->lut; + display_info.disp_reg_address = (unsigned long) &plat_regs; +} + +int +platinum_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || platinum_reg_init[mode->mode-1] == 0) + return -EINVAL; + if (mode->depth != 8 && mode->depth != 16 && mode->depth != 24 && mode->depth != 32) + return -EINVAL; + + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + + if (platinum_vram_reqd(mode->mode, cmode) > total_vram) + return -EINVAL; + + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + platinum_init(); + } + return 0; +} + +void +platinum_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + cmap_regs->addr = index + i; eieio(); + cmap_regs->lut = red[i]; eieio(); + cmap_regs->lut = green[i]; eieio(); + cmap_regs->lut = blue[i]; eieio(); + } +} + +void +platinum_set_blanking(int blank_mode) +{ +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/platinum.h linux/drivers/macintosh/platinum.h --- v2.1.50/linux/drivers/macintosh/platinum.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/platinum.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,17 @@ +/* + * Exported procedures for the PowerMac "platinum" display adaptor. + * + * Copyright (C) 1996 Paul Mackerras and Mark Abene. + * + * 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. + */ + +extern void map_platinum(struct device_node *); +extern void platinum_init(void); +extern int platinum_setmode(struct vc_mode *mode, int doit); +extern void platinum_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void platinum_set_blanking(int blank_mode); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/pmac-cons.c linux/drivers/macintosh/pmac-cons.c --- v2.1.50/linux/drivers/macintosh/pmac-cons.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/pmac-cons.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,1312 @@ +/* + * pmac-cons.c: Console support for PowerMac (PCI-based). + * + * Copyright (C) 1996 Paul Mackerras. + * 7200/Platinum code hacked by Mark Abene. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmac-cons.h" +#include "control.h" +#include "platinum.h" +#include "valkyrie.h" +#ifdef CONFIG_ATY_VIDEO +#include "aty.h" +#endif +#ifdef CONFIG_IMSTT_VIDEO +#include "imstt.h" +#endif + +int video_mode = VMODE_NVRAM; +int color_mode = CMODE_NVRAM; + +/* + * The format of "screen_info" is strange, and due to early + * i386-setup code. This is just enough to make the console + * code think we're on a EGA+ colour display. + */ +struct screen_info screen_info = { + 0, 0, /* orig-x, orig-y */ + {0, 0}, /* unused1 */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0, /* unused [short] */ + 0, /* ega_bx */ + 0, /* unused [short] */ + 25, /* orig-video-lines */ + 0, /* isVGA */ + 16 /* video points */ +}; + +/* + * We allocate enough character+attribute memory for the largest + * screen resolution supported. + */ +#define MAX_TEXT_COLS (1280/8) +#define MAX_TEXT_ROWS (1024/16) + +/* + * We get a sense value from the monitor and use it to choose + * what resolution to use. This structure maps sense values + * to display mode values (which determine the resolution and + * frequencies). + */ +struct mon_map { + int sense; + int vmode; +} monitor_map [] = { + {0x000, VMODE_1280_1024_75}, /* 21" RGB */ + {0x114, VMODE_640_870_75P}, /* Portrait Monochrome */ + {0x221, VMODE_512_384_60}, /* 12" RGB*/ + {0x331, VMODE_1280_1024_75}, /* 21" RGB (Radius) */ + {0x334, VMODE_1280_1024_75}, /* 21" mono (Radius) */ + {0x335, VMODE_1280_1024_75}, /* 21" mono */ + {0x40A, VMODE_640_480_60I}, /* NTSC */ + {0x51E, VMODE_640_870_75P}, /* Portrait RGB */ + {0x603, VMODE_832_624_75}, /* 12"-16" multiscan */ + {0x60b, VMODE_1024_768_70}, /* 13"-19" multiscan */ + {0x623, VMODE_1152_870_75}, /* 13"-21" multiscan */ + {0x62b, VMODE_640_480_67}, /* 13"/14" RGB */ + {0x700, VMODE_640_480_50I}, /* PAL */ + {0x714, VMODE_640_480_60I}, /* NTSC */ + {0x717, VMODE_800_600_75}, /* VGA */ + {0x72d, VMODE_832_624_75}, /* 16" RGB (Goldfish) */ + {0x730, VMODE_768_576_50I}, /* PAL (Alternate) */ + {0x73a, VMODE_1152_870_75}, /* 3rd party 19" */ + {-1, VMODE_640_480_60}, /* catch-all, must be last */ +}; + +int +map_monitor_sense(int sense) +{ + struct mon_map *map; + + for (map = monitor_map; map->sense >= 0; ++map) + if (map->sense == sense) + break; + return map->vmode; +} + +/* + * Horizontal and vertical resolution for each mode. + */ +struct vmode_attr vmode_attrs[VMODE_MAX] = { + {512, 384, 60, 1}, + {512, 384, 60}, + {640, 480, 50, 1}, + {640, 480, 60, 1}, + {640, 480, 60}, + {640, 480, 67}, + {640, 870, 75}, + {768, 576, 50, 1}, + {800, 600, 56}, + {800, 600, 60}, + {800, 600, 72}, + {800, 600, 75}, + {832, 624, 75}, + {1024, 768, 60}, + {1024, 768, 72}, + {1024, 768, 75}, + {1024, 768, 75}, + {1152, 870, 75}, + {1280, 960, 75}, + {1280, 1024, 75} +}; + +static void invert_cursor(int); +static int map_unknown(struct device_node *); +static void unknown_init(void); + +struct display_interface { + char *name; + void (*map_interface)(struct device_node *); + void (*init_interface)(void); + int (*setmode)(struct vc_mode *, int); + void (*set_palette)(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); + void (*set_blanking)(int blank_mode); +} displays[] = { + { "control", map_control_display, control_init, + control_setmode, control_set_palette, control_set_blanking }, + { "platinum", map_platinum, platinum_init, + platinum_setmode, platinum_set_palette, platinum_set_blanking }, + { "valkyrie", map_valkyrie_display, valkyrie_init, + valkyrie_setmode, valkyrie_set_palette, valkyrie_set_blanking }, +#ifdef CONFIG_ATY_VIDEO + { "ATY,mach64", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,XCLAIM", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,264VT", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,mach64ii", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, +#if 0 /* not right for 3D mach64 yet */ + { "ATY,264GT-B", map_aty_display, aty_init, + aty_setmode, aty_set_palette, aty_set_blanking }, + { "ATY,mach64_3D_pcc", map_aty_display, aty_init, + aty_setmode, aty_set_palette }, +#endif +#endif +#ifdef CONFIG_IMSTT_VIDEO + { "IMS,tt128mb", map_imstt_display, imstt_init, + imstt_setmode, imstt_set_palette, imstt_set_blanking }, +#endif + { NULL } +}; + +struct display_interface unknown_display = { + "unknown", NULL, unknown_init, NULL, NULL +}; + +static struct display_interface *current_display; + +static int cursor_pos = -1; +static unsigned *cursor_fb; /* address of cursor pos in frame buffer */ +static unsigned cursor_bits; /* bits changed to turn cursor on */ + +int pixel_size; /* in bytes */ +int n_scanlines; /* # of scan lines */ +int line_pitch; /* # bytes in 1 scan line */ +int row_pitch; /* # bytes in 1 row of characters */ +unsigned char *fb_start; /* addr of top left pixel of top left char */ +struct vc_mode display_info; + +extern int screen_initialized; /* in arch/ppc/pmac/prom.c */ + +#define cmapsz (16*256) +extern unsigned char vga_font[cmapsz]; + +static inline unsigned pixel32(int currcons, int cidx) +{ + cidx *= 3; + return (palette[cidx] << 16) | (palette[cidx + 1] << 8) + | palette[cidx + 2]; +} + +static inline unsigned pixel16(int currcons, int cidx) +{ + unsigned p; + + p = ((cidx << 10) & 0x7c00) + ((cidx << 5) & 0x03e0) + + (cidx & 0x1f); + return (p << 16) | p; +} + +void +__set_origin(unsigned short offset) +{ +} + +static void +invert_cursor(int cpos) +{ + int row, col; + int l, c, nw; + unsigned *fb, mask; + int currcons = fg_console; /* for `color', which is a macro */ + + if (cpos == -1) { + /* turning cursor off */ + fb = cursor_fb; + mask = cursor_bits; + } else { + row = cpos / video_num_columns; + col = cpos - row * video_num_columns; + fb = (unsigned *) (fb_start + row * row_pitch + + col * pixel_size * 8); + switch (color_mode) { + case CMODE_16: + mask = pixel16(currcons, foreground) + ^ pixel16(currcons, background >> 4); + break; + default: + mask = (color ^ (color >> 4)) & 0xf; + mask |= mask << 8; + mask |= mask << 16; + break; + } + cursor_fb = fb; + cursor_bits = mask; + } + nw = pixel_size * 2; /* pixel_size * 8 (char width) / 4 */ + for (l = 0; l < 16; ++l) { + for (c = 0; c < nw; ++c) + fb[c] ^= mask; + fb = (unsigned *) ((char *)fb + line_pitch); + } +} + +void +hide_cursor() +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (cursor_pos != -1) { + invert_cursor(-1); + cursor_pos = -1; + } + restore_flags(flags); +} + +void +set_cursor(int currcons) +{ + unsigned long flags; + int old_cursor; + + if (currcons != fg_console || console_blanked) + return; + + save_flags(flags); + cli(); + if (!deccm) { + hide_cursor(); + } else { + old_cursor = cursor_pos; + cursor_pos = (pos - video_mem_base) >> 1; + if (old_cursor != -1) + invert_cursor(-1); + invert_cursor(cursor_pos); + } + restore_flags(flags); +} + +/* + * NOTE: get_scrmem() and set_scrmem() are here only because + * the VGA version of set_scrmem() has some direct VGA references. + */ +void +get_scrmem(int currcons) +{ + memcpyw((unsigned short *)vc_scrbuf[currcons], + (unsigned short *)origin, video_screen_size); + origin = video_mem_start = (unsigned long)vc_scrbuf[currcons]; + scr_end = video_mem_end = video_mem_start + video_screen_size; + pos = origin + y*video_size_row + (x<<1); +} + +void +set_scrmem(int currcons, long offset) +{ + if (video_mem_term - video_mem_base < offset + video_screen_size) + offset = 0; + memcpyw((unsigned short *)(video_mem_base + offset), + (unsigned short *) origin, video_screen_size); + video_mem_start = video_mem_base; + video_mem_end = video_mem_term; + origin = video_mem_base + offset; + scr_end = origin + video_screen_size; + pos = origin + y*video_size_row + (x<<1); +} + +int +set_get_cmap(unsigned char *p, int set) +{ + int i, j, err; + + err = verify_area(set? VERIFY_READ: VERIFY_WRITE, p, 48); + if (err) + return err; + + for (i = 0; i < 16; ++i) { + if (set) { + get_user(default_red[i], p++); + get_user(default_grn[i], p++); + get_user(default_blu[i], p++); + } else { + put_user(default_red[i], p++); + put_user(default_grn[i], p++); + put_user(default_blu[i], p++); + } + } + + if (set) { + for (j = 0; j < MAX_NR_CONSOLES; ++j) { + if (!vc_cons_allocated(j)) + continue; + for (i = 0; i < 16; ++i) { + vc_cons[j].d->vc_palette[3*i+0] = default_red[i]; + vc_cons[j].d->vc_palette[3*i+1] = default_grn[i]; + vc_cons[j].d->vc_palette[3*i+2] = default_blu[i]; + } + } + set_palette(); + } + + return 0; +} + +int +set_get_font(char *p, int set, int ch512) +{ + return 0; +} + +void +set_palette() +{ + int i, j, n; + unsigned char red[16], green[16], blue[16]; + + if (console_blanked || current_display == NULL + || current_display->set_palette == NULL + || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) + return; + + for (i = j = 0; i < 16; ++i) { + n = color_table[i] & 0xf; + red[n] = vc_cons[fg_console].d->vc_palette[j++]; + green[n] = vc_cons[fg_console].d->vc_palette[j++]; + blue[n] = vc_cons[fg_console].d->vc_palette[j++]; + } + (*current_display->set_palette)(red, green, blue, 0, 16); +} + +void +pmac_init_palette() +{ + int i, n; + unsigned char red[16], green[16], blue[16]; + + for (i = 0; i < 16; ++i) { + n = color_table[i] & 0xf; + red[n] = default_red[i]; + green[n] = default_grn[i]; + blue[n] = default_blu[i]; + } + (*current_display->set_palette)(red, green, blue, 0, 16); +} + +static int vesa_blanking_mode; +static int vesa_blanked; + +void +vesa_blank() +{ + if (vesa_blanking_mode == 0 || vesa_blanked + || current_display == NULL + || current_display->set_blanking == NULL) + return; + (*current_display->set_blanking)(vesa_blanking_mode); + vesa_blanked = vesa_blanking_mode; +} + +void +vesa_unblank() +{ + if (vesa_blanked == 0 + || current_display == NULL + || current_display->set_blanking == NULL) + return; + (*current_display->set_blanking)(VESA_NO_BLANKING); + vesa_blanked = VESA_NO_BLANKING; +} + +void +set_vesa_blanking(const unsigned long arg) +{ + unsigned char *argp = (unsigned char *)(arg + 1); + unsigned int mode; + + if (verify_area(VERIFY_READ, argp, 1)) + return; + + get_user(mode, argp); + vesa_blanking_mode = (mode <= VESA_POWERDOWN)? mode: \ + DEFAULT_VESA_BLANKING_MODE; +} + +void +vesa_powerdown() +{ + if (vesa_blanked == 0 || vesa_blanked == VESA_POWERDOWN + || current_display == NULL + || current_display->set_blanking == NULL) + return; + (*current_display->set_blanking)(VESA_POWERDOWN); + vesa_blanked = VESA_POWERDOWN; +} + +void +memsetw(unsigned short *p, unsigned short c, unsigned count) +{ + count /= 2; + if ((unsigned long)(p + count) > video_mem_base + && (unsigned long)p < video_mem_term) { + for (; p < (unsigned short *) video_mem_base && count != 0; --count) + *p++ = c; + for (; p < (unsigned short *) video_mem_term && count != 0; --count) { + if (*p != c) { + *p = c; + pmac_blitc(c, (unsigned long)p); + } + ++p; + } + } + for (; count != 0; --count) + *p++ = c; +} + +void +memcpyw(unsigned short *to, unsigned short *from, unsigned count) +{ + unsigned short c; + + count /= 2; + if ((unsigned long)(to + count) > video_mem_base + && (unsigned long)to < video_mem_term) { + for (; to < (unsigned short *) video_mem_base && count != 0; --count) + *to++ = *from++; + for (; to < (unsigned short *) video_mem_term && count != 0; --count) { + c = *from++; + if (*to != c) { + *to = c; + pmac_blitc(c, (unsigned long)to); + } + ++to; + } + } + for (; count != 0; --count) + *to++ = *from++; +} + +void +pmac_find_display() +{ + struct display_interface *disp; + struct device_node *dp; + struct vmode_attr *ap; + + current_display = NULL; + if (serial_console) + return; + for (disp = displays; disp->name != NULL; ++disp) { + dp = find_devices(disp->name); + if (dp == 0) + continue; + current_display = disp; + disp->map_interface(dp); + break; + } + + if (current_display == NULL) { + /* + * We haven't found a display that we know about, + * but if there is a display with sufficient prom support, + * we may be able to use it in a limited fashion. + * If there is, it has already been opened in prom_init(). + */ + if (prom_display_path[0] != 0) { + dp = find_path_device(prom_display_path); + if (dp != 0 && map_unknown(dp)) + current_display = &unknown_display; + else + printk(KERN_INFO "Can't use %s for display\n", + prom_display_path); + } + } + + if (current_display == NULL + || video_mode <= 0 || video_mode > VMODE_MAX) { + printk(KERN_INFO "No usable display device found" + "- using serial console\n"); + serial_console = 1; /* no screen - fall back to serial */ + return; + } + ap = &vmode_attrs[video_mode - 1]; + screen_info.orig_video_cols = ap->hres / 8; + screen_info.orig_video_lines = ap->vres / 16; + printk("using video mode %d (%dx%d at %dHz%s), %d bits/pixel\n", + video_mode, ap->hres, ap->vres, ap->vfreq, + ap->interlaced? " interlaced": "", + (color_mode + 1) * 8); +} + +int +pmac_display_supported(const char *name) +{ + struct display_interface *disp; + + for (disp = displays; disp->name != NULL; ++disp) + if (strcmp(name, disp->name) == 0) + return 1; + return 0; +} + +int +console_getmode(struct vc_mode *mode) +{ + *mode = display_info; + return 0; +} + +int +console_setmode(struct vc_mode *mode, int doit) +{ + int err; + + if (current_display == NULL || current_display->setmode == NULL) + return -EINVAL; + err = (*current_display->setmode)(mode, doit); + if (doit && err == 0) + memset((void *)video_mem_base, 0, video_screen_size); + return err; +} + +int +console_powermode(int mode) +{ + if (mode == VC_POWERMODE_INQUIRY) + return vesa_blanked; + if (mode < VESA_NO_BLANKING || mode > VESA_POWERDOWN) + return -EINVAL; + if (current_display == NULL || current_display->set_blanking == NULL) + return -ENXIO; + (*current_display->set_blanking)(mode); + vesa_blanked = mode; + return 0; +} + +void +pmac_cons_setup(char *str, int *ints) +{ + if (strcmp(str, "ttya") == 0 || strcmp(str, "modem") == 0) + serial_console = 1; + else if (strcmp(str, "ttyb") == 0 || strcmp(str, "printer") == 0) + serial_console = 2; +} + +void +pmac_vmode_setup(char *str, int *ints) +{ + if (ints[0] >= 1) + video_mode = ints[1]; + if (ints[0] >= 2) + color_mode = ints[2]; +} + +unsigned long +con_type_init(unsigned long mem_start, const char **type_p) +{ + if (current_display == NULL) + panic("no display available"); + current_display->init_interface(); + screen_initialized = 1; /* inhibits prom_print */ + can_do_color = 1; + video_type = VIDEO_TYPE_PMAC; + *type_p = display_info.name; + video_mem_base = mem_start; + mem_start += MAX_TEXT_COLS * MAX_TEXT_ROWS * 2; + video_mem_term = mem_start; + memset((char *) video_mem_base, 0, video_screen_size); + return mem_start; +} + +static __inline__ void +draw_logo_8(void) +{ + unsigned char *fb = fb_start; + unsigned char *p = linux_logo; + int yy; + + (*current_display->set_palette) + (linux_logo_red, linux_logo_green, linux_logo_blue, + 32, LINUX_LOGO_COLORS); + + for (yy = 0; yy < LINUX_LOGO_HEIGHT; ++yy) { + memcpy(fb, p, LINUX_LOGO_WIDTH); + fb += line_pitch; + p += LINUX_LOGO_WIDTH; + } +} + +static __inline__ void +draw_logo_15(void) +{ + unsigned short *fb; + unsigned char *row = fb_start; + unsigned char *p = linux_logo; + int i, xx, yy; + unsigned char grey[16]; + + /* + * For 15-bit mode, treat the screen as a 4/4/4 TrueColor. + */ + for (i = 0; i < 16; ++i) + grey[i] = i << 4; + (*current_display->set_palette)(grey, grey, grey, 16, 16); + + for (yy = 0; yy < LINUX_LOGO_HEIGHT; ++yy) { + fb = (unsigned short *) row; + for (xx = 0; xx < LINUX_LOGO_WIDTH; ++xx) { + i = *p++ - 32; + *fb++ = 0x4210 + + ((linux_logo_red[i] & 0xf0) << 6) + + ((linux_logo_green[i] & 0xf0) << 1) + + (linux_logo_blue[i] >> 4); + } + row += line_pitch; + } +} + +static __inline__ void +draw_logo_24(void) +{ + unsigned long *fb; + unsigned char *row = fb_start; + unsigned char *p = linux_logo; + int xx, yy, v; + + (*current_display->set_palette) + (linux_logo_red, linux_logo_green, linux_logo_blue, + 32, LINUX_LOGO_COLORS); + + for (yy = 0; yy < LINUX_LOGO_HEIGHT; ++yy) { + fb = (unsigned long *) row; + for (xx = 0; xx < LINUX_LOGO_WIDTH; ++xx) { + v = *p++; + v |= v << 8; + v |= v << 16; + *fb++ = v; + } + row += line_pitch; + } +} + +void +con_type_init_finish(void) +{ + char *p; + int c; + unsigned short *addr; + char xy[2]; + int currcons = 0; /* for `attr', which is a macro */ + + if (current_display == NULL + || current_display->set_palette == NULL) + return; + + switch (color_mode) { + case CMODE_8: + draw_logo_8(); + break; + + case CMODE_16: + draw_logo_15(); + break; + + case CMODE_32: + draw_logo_24(); + break; + } + xy[0] = 0; + xy[1] = (LINUX_LOGO_HEIGHT + 16) / 16; + putconsxy(0, xy); + + p = "PowerMac/Linux " UTS_RELEASE; + addr = (unsigned short *) video_mem_base + 2 * video_num_columns + + LINUX_LOGO_WIDTH / 8 + 8; + for (; *p; ++p) { + c = (attr << 8) + *p; + scr_writew(c, addr); + ++addr; + } +} + +int +con_adjust_height(unsigned long height) +{ + return -EINVAL; +} + +static unsigned long expand_bits_8[16] = { + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +static unsigned long expand_bits_16[4] = { + 0x00000000, + 0x0000ffff, + 0xffff0000, + 0xffffffff +}; + +void +pmac_blitc(unsigned charattr, unsigned long addr) +{ + int col, row, fg, bg, l, bits; + unsigned char *fp; + unsigned long *fb; + static int cached_row_start, cached_row_end = -1; + static unsigned char *cached_fb; + static int cached_attr = -1; + static unsigned long cached_fg, cached_bg; + + col = (addr - video_mem_base) / 2; + if (cursor_pos == col) + cursor_pos = -1; + if (!(col >= cached_row_start && col < cached_row_end)) { + row = col / video_num_columns; + cached_row_start = row * video_num_columns; + cached_row_end = cached_row_start + video_num_columns; + cached_fb = fb_start + row * row_pitch; + } + fb = (unsigned long *) + (cached_fb + (col - cached_row_start) * pixel_size * 8); + + if ((charattr & 0xff00) != cached_attr) { + fg = (charattr >> 8) & 0xf; + bg = (charattr >> 12) & 0xf; + switch (color_mode) { + case CMODE_16: + fg = pixel16(fg_console, fg); + bg = pixel16(fg_console, bg); + break; + default: + fg += fg << 8; + fg += fg << 16; + bg += bg << 8; + bg += bg << 16; + } + fg ^= bg; + cached_fg = fg; + cached_bg = bg; + } else { + fg = cached_fg; + bg = cached_bg; + } + + fp = &vga_font[(charattr & 0xff) * 16]; + switch (color_mode) { + case CMODE_32: + for (l = 0; l < 16; ++l) { + bits = *fp++; + fb[0] = (-(bits >> 7) & fg) ^ bg; + fb[1] = (-((bits >> 6) & 1) & fg) ^ bg; + fb[2] = (-((bits >> 5) & 1) & fg) ^ bg; + fb[3] = (-((bits >> 4) & 1) & fg) ^ bg; + fb[4] = (-((bits >> 3) & 1) & fg) ^ bg; + fb[5] = (-((bits >> 2) & 1) & fg) ^ bg; + fb[6] = (-((bits >> 1) & 1) & fg) ^ bg; + fb[7] = (-(bits & 1) & fg) ^ bg; + fb = (unsigned long *) ((char *)fb + line_pitch); + } + break; + case CMODE_16: + for (l = 0; l < 16; ++l) { + bits = *fp++; + fb[0] = (expand_bits_16[bits >> 6] & fg) ^ bg; + fb[1] = (expand_bits_16[(bits >> 4) & 3] & fg) ^ bg; + fb[2] = (expand_bits_16[(bits >> 2) & 3] & fg) ^ bg; + fb[3] = (expand_bits_16[bits & 3] & fg) ^ bg; + fb = (unsigned long *) ((char *)fb + line_pitch); + } + break; + default: + for (l = 0; l < 16; ++l) { + bits = *fp++; + fb[0] = (expand_bits_8[bits >> 4] & fg) ^ bg; + fb[1] = (expand_bits_8[bits & 0xf] & fg) ^ bg; + fb = (unsigned long *) ((char *)fb + line_pitch); + } + } +} + + +/* + * The following provides a very basic screen driver for displays + * that we basically don't know anything about, but which we can + * initialize by using their Open Firmware "open" method. + */ + +static int unknown_modes[] = { + VMODE_512_384_60, + VMODE_640_480_60, + VMODE_800_600_60, + VMODE_832_624_75, + VMODE_1024_768_60, + VMODE_1152_870_75, + VMODE_1280_960_75, + VMODE_1280_1024_75, + 0 +}; + +static unsigned char *frame_buffer; + +static int map_unknown(struct device_node *dp) +{ + int i, mode; + int width; + int *pp, len; + unsigned *up, address; + + printk("map_unknown(%p), name = %s\n", dp, dp->full_name); + + /* check the depth */ + if ((pp = (int *) get_property(dp, "depth", &len)) != NULL + && len == sizeof(int) && *pp != 8) { + printk("%s: can't use depth = %d\n", dp->full_name, *pp); + return 0; + } + + width = 640; /* default values */ + n_scanlines = 480; + if ((pp = (int *) get_property(dp, "width", &len)) != NULL + && len == sizeof(int)) + width = *pp; + if ((pp = (int *) get_property(dp, "height", &len)) != NULL + && len == sizeof(int)) + n_scanlines = *pp; + line_pitch = width; + if ((pp = (int *) get_property(dp, "linebytes", &len)) != NULL + && len == sizeof(int)) + line_pitch = *pp; + printk(KERN_INFO "width=%d height=%d pitch=%d\n", + width, n_scanlines, line_pitch); + + len = n_scanlines * line_pitch; + if ((up = (unsigned *) get_property(dp, "address", &len)) != NULL + && len == sizeof(unsigned)) { + address = *up; + } else { + for (i = 0; i < dp->n_addrs; ++i) + if (dp->addrs[i].size >= len) + break; + if (i >= dp->n_addrs) { + printk("no framebuffer address found for %s\n", + dp->full_name); + return 0; + } + address = dp->addrs[i].address; + /* temporary kludge for valkyrie */ + if (strcmp(dp->name, "valkyrie") == 0) + address += 0x1000; + } + printk(KERN_INFO "%s: using address %x\n", dp->full_name, address); + frame_buffer = ioremap(address, len); + + video_mode = 0; + color_mode = CMODE_8; + pixel_size = 1; + + for (i = 0; (mode = unknown_modes[i]) != 0; ++i) { + if (vmode_attrs[mode-1].hres <= width + && vmode_attrs[mode-1].vres <= n_scanlines) + video_mode = mode; + } + if (video_mode == 0) { + printk(KERN_INFO "%s: no mode found for %d x %d\n", + dp->full_name, width, n_scanlines); + return 0; + } + + display_info.height = n_scanlines; + display_info.width = width; + display_info.depth = 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, dp->name, sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer; + display_info.cmap_adr_address = 0; + display_info.cmap_data_address = 0; + display_info.disp_reg_address = 0; + + return 1; +} + +static void +unknown_init() +{ + unsigned *p; + int i; + + row_pitch = line_pitch * 16; + fb_start = frame_buffer; + + /* Clear screen */ + p = (unsigned *) frame_buffer; + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; +} + + +unsigned char vga_font[cmapsz] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +}; diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/pmac-cons.h linux/drivers/macintosh/pmac-cons.h --- v2.1.50/linux/drivers/macintosh/pmac-cons.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/pmac-cons.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,90 @@ +/* + * Definitions for display drivers for console use on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern int serial_console; /* set to use serial port as console */ + +/* + * Video mode values. + * These are supposed to be the same as the values that + * Apple uses in MacOS. + */ +#define VMODE_NVRAM 0 /* use value stored in nvram */ +#define VMODE_512_384_60I 1 /* 512x384, 60Hz interlaced (NTSC) */ +#define VMODE_512_384_60 2 /* 512x384, 60Hz */ +#define VMODE_640_480_50I 3 /* 640x480, 50Hz interlaced (PAL) */ +#define VMODE_640_480_60I 4 /* 640x480, 60Hz interlaced (NTSC) */ +#define VMODE_640_480_60 5 /* 640x480, 60Hz (VGA) */ +#define VMODE_640_480_67 6 /* 640x480, 67Hz */ +#define VMODE_640_870_75P 7 /* 640x870, 75Hz (portrait) */ +#define VMODE_768_576_50I 8 /* 768x576, 50Hz (PAL full frame) */ +#define VMODE_800_600_56 9 /* 800x600, 56Hz */ +#define VMODE_800_600_60 10 /* 800x600, 60Hz */ +#define VMODE_800_600_72 11 /* 800x600, 72Hz */ +#define VMODE_800_600_75 12 /* 800x600, 75Hz */ +#define VMODE_832_624_75 13 /* 832x624, 75Hz */ +#define VMODE_1024_768_60 14 /* 1024x768, 60Hz */ +#define VMODE_1024_768_70 15 /* 1024x768, 70Hz (or 72Hz?) */ +#define VMODE_1024_768_75V 16 /* 1024x768, 75Hz (VESA) */ +#define VMODE_1024_768_75 17 /* 1024x768, 75Hz */ +#define VMODE_1152_870_75 18 /* 1152x870, 75Hz */ +#define VMODE_1280_960_75 19 /* 1280x960, 75Hz */ +#define VMODE_1280_1024_75 20 /* 1280x1024, 75Hz */ +#define VMODE_MAX 20 +#define VMODE_CHOOSE 99 /* choose based on monitor sense */ + +/* + * Color mode values, used to select number of bits/pixel. + */ +#define CMODE_NVRAM -1 /* use value stored in nvram */ +#define CMODE_8 0 /* 8 bits/pixel */ +#define CMODE_16 1 /* 16 (actually 15) bits/pixel */ +#define CMODE_32 2 /* 32 (actually 24) bits/pixel */ + +extern int video_mode; +extern int color_mode; + +/* + * Addresses in NVRAM where video mode and pixel size are stored. + */ +#define NV_VMODE 0x140f +#define NV_CMODE 0x1410 + +/* + * Horizontal and vertical resolution information. + */ +extern struct vmode_attr { + int hres; + int vres; + int vfreq; + int interlaced; +} vmode_attrs[VMODE_MAX]; + +extern struct vc_mode display_info; + +#define DEFAULT_VESA_BLANKING_MODE VESA_NO_BLANKING + +extern int pixel_size; /* in bytes */ +extern int n_scanlines; /* # of scan lines */ +extern int line_pitch; /* # bytes in 1 scan line */ +extern int row_pitch; /* # bytes in 1 row of characters */ +extern unsigned char *fb_start; /* addr of top left pixel of top left char */ + +/* map monitor sense value to video mode */ +extern int map_monitor_sense(int sense); + +void set_palette(void); +void pmac_find_display(void); +void vesa_blank(void); +void vesa_unblank(void); +void set_vesa_blanking(const unsigned long); +void vesa_powerdown(void); +void hide_cursor(void); +void pmac_init_palette(void); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/valkyrie.c linux/drivers/macintosh/valkyrie.c --- v2.1.50/linux/drivers/macintosh/valkyrie.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/valkyrie.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,321 @@ +/* + * valkyrie.c: Console support for PowerMac "valkyrie" display adaptor. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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 +#include +#include +#include "pmac-cons.h" +#include "valkyrie.h" + +/* + * Structure of the registers for the Valkyrie colormap registers. + */ +struct cmap_regs { + unsigned char addr; + char pad1[7]; + unsigned char lut; +}; + +/* + * Structure of the registers for the "valkyrie" display adaptor. + */ +#define PAD(x) char x[7] + +struct valkyrie_regs { + unsigned char mode; + PAD(pad0); + unsigned char depth; + PAD(pad1); + unsigned char status; + PAD(pad2); + unsigned char reg3; + PAD(pad3); + unsigned char intr; + PAD(pad4); + unsigned char reg5; + PAD(pad5); + unsigned char intr_enb; + PAD(pad6); + unsigned char msense; + PAD(pad7); +}; + +static void set_valkyrie_clock(unsigned char *params); +static int read_valkyrie_sense(void); + +static unsigned char *frame_buffer; +static struct cmap_regs *cmap_regs; +static struct valkyrie_regs *disp_regs; + +/* + * Register initialization tables for the valkyrie display. + * + * Dot clock rate is + * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0]. + */ +struct valkyrie_regvals { + unsigned char mode; + unsigned char clock_params[3]; + int pitch[2]; /* bytes/line, indexed by color_mode */ +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct valkyrie_regvals valkyrie_reg_init_15 = { + 15, + { 12, 30, 3 }, /* pixel clock = 78.12MHz for V=72.12Hz */ + { 1024, 0 } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct valkyrie_regvals valkyrie_reg_init_14 = { + 14, + { 15, 31, 3 }, /* pixel clock = 64.58MHz for V=59.62Hz */ + { 1024, 0 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct valkyrie_regvals valkyrie_reg_init_13 = { + 9, + { 23, 42, 3 }, /* pixel clock = 57.07MHz for V=74.27Hz */ + { 832, 0 } +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct valkyrie_regvals valkyrie_reg_init_11 = { + 13, + { 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */ + { 800, 0 } +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct valkyrie_regvals valkyrie_reg_init_10 = { + 12, + { 20, 53, 2 }, /* pixel clock = 41.41MHz for V=59.78Hz */ + { 800, 0 } +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct valkyrie_regvals valkyrie_reg_init_6 = { + 6, + { 14, 27, 2 }, /* pixel clock = 30.13MHz for V=66.43Hz */ + { 640, 1280 } +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct valkyrie_regvals valkyrie_reg_init_5 = { + 11, + { 23, 37, 2 }, /* pixel clock = 25.14MHz for V=59.85Hz */ + { 640, 1280 } +}; + +static struct valkyrie_regvals *valkyrie_reg_init[20] = { + NULL, NULL, NULL, NULL, + &valkyrie_reg_init_5, + &valkyrie_reg_init_6, + NULL, NULL, NULL, + &valkyrie_reg_init_10, + &valkyrie_reg_init_11, + NULL, + &valkyrie_reg_init_13, + &valkyrie_reg_init_14, + &valkyrie_reg_init_15, + NULL, NULL, NULL, NULL, NULL +}; + +/* + * Get the monitor sense value. + */ +static int +read_valkyrie_sense() +{ + int sense; + + out_8(&disp_regs->msense, 0); /* release all lines */ + __delay(20000); + sense = (in_8(&disp_regs->msense) & 0x70) << 4; + + /* drive each sense line low in turn and collect the other 2 */ + out_8(&disp_regs->msense, 4); /* drive A low */ + __delay(20000); + sense |= in_8(&disp_regs->msense) & 0x30; + out_8(&disp_regs->msense, 2); /* drive B low */ + __delay(20000); + sense |= ((in_8(&disp_regs->msense) & 0x40) >> 3) + | ((in_8(&disp_regs->msense) & 0x10) >> 2); + out_8(&disp_regs->msense, 1); /* drive C low */ + __delay(20000); + sense |= (in_8(&disp_regs->msense) & 0x60) >> 5; + + out_8(&disp_regs->msense, 7); + return sense; +} + +void +map_valkyrie_display(struct device_node *dp) +{ + int sense; + unsigned long addr; + + if (dp->next != 0) + printk("Warning: only using first valkyrie display device\n"); + if (dp->n_addrs != 1) + panic("expecting 1 address for valkyrie (got %d)", dp->n_addrs); + + /* Map in frame buffer and registers */ + addr = dp->addrs[0].address; + frame_buffer = ioremap(addr, 0x100000); + disp_regs = ioremap(addr + 0x30a000, 4096); + cmap_regs = ioremap(addr + 0x304000, 4096); + + /* Read the monitor sense value and choose the video mode */ + sense = read_valkyrie_sense(); + if (video_mode == VMODE_NVRAM) { + video_mode = nvram_read_byte(NV_VMODE); + if (video_mode <= 0 || video_mode > VMODE_MAX + || valkyrie_reg_init[video_mode-1] == 0) + video_mode = VMODE_CHOOSE; + } + if (video_mode == VMODE_CHOOSE) + video_mode = map_monitor_sense(sense); + if (valkyrie_reg_init[video_mode-1] == 0) + video_mode = VMODE_640_480_60; + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + if (color_mode == CMODE_NVRAM) + color_mode = nvram_read_byte(NV_CMODE); + if (color_mode < CMODE_8 || color_mode > CMODE_16 + || valkyrie_reg_init[video_mode-1]->pitch[color_mode] == 0) + color_mode = CMODE_8; + + printk("Monitor sense value = 0x%x, ", sense); +} + +static void +set_valkyrie_clock(unsigned char *params) +{ + struct cuda_request req; + int i; + + for (i = 0; i < 3; ++i) { + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x50, i + 1, params[i]); + while (!req.got_reply) + cuda_poll(); + } +} + +void +valkyrie_init() +{ + int i, yoff, hres; + unsigned *p; + struct valkyrie_regvals *init; + + if (video_mode <= 0 || video_mode > VMODE_MAX + || (init = valkyrie_reg_init[video_mode-1]) == 0) + panic("valkyrie: display mode %d not supported", video_mode); + n_scanlines = vmode_attrs[video_mode-1].vres; + hres = vmode_attrs[video_mode-1].hres; + pixel_size = 1 << color_mode; + line_pitch = init->pitch[color_mode]; + row_pitch = line_pitch * 16; + + /* Reset the valkyrie */ + out_8(&disp_regs->status, 0); + udelay(100); + + /* Initialize display timing registers */ + out_8(&disp_regs->mode, init->mode | 0x80); + out_8(&disp_regs->depth, color_mode + 3); + set_valkyrie_clock(init->clock_params); + udelay(100); + + pmac_init_palette(); /* Initialize colormap */ + + /* Turn on display */ + out_8(&disp_regs->mode, init->mode); + + yoff = (n_scanlines % 16) / 2; + fb_start = frame_buffer + yoff * line_pitch + 0x1000; + + /* Clear screen */ + p = (unsigned *) (frame_buffer + 0x1000); + for (i = n_scanlines * line_pitch / sizeof(unsigned); i != 0; --i) + *p++ = 0; + + display_info.height = n_scanlines; + display_info.width = hres; + display_info.depth = pixel_size * 8; + display_info.pitch = line_pitch; + display_info.mode = video_mode; + strncpy(display_info.name, "valkyrie", sizeof(display_info.name)); + display_info.fb_address = (unsigned long) frame_buffer + 0x1000; + display_info.cmap_adr_address = (unsigned long) &cmap_regs->addr; + display_info.cmap_data_address = (unsigned long) &cmap_regs->lut; + display_info.disp_reg_address = (unsigned long) &disp_regs; +} + +int +valkyrie_setmode(struct vc_mode *mode, int doit) +{ + int cmode; + + switch (mode->depth) { + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + if (mode->mode <= 0 || mode->mode > VMODE_MAX + || valkyrie_reg_init[mode->mode-1] == 0 + || valkyrie_reg_init[mode->mode-1]->pitch[cmode] == 0) + return -EINVAL; + if (doit) { + video_mode = mode->mode; + color_mode = cmode; + valkyrie_init(); + } + return 0; +} + +void +valkyrie_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors) +{ + int i; + + for (i = 0; i < ncolors; ++i) { + out_8(&cmap_regs->addr, index + i); + udelay(1); + out_8(&cmap_regs->lut, red[i]); + out_8(&cmap_regs->lut, green[i]); + out_8(&cmap_regs->lut, blue[i]); + } +} + +void +valkyrie_set_blanking(int blank_mode) +{ + /* don't know how to do this yet */ +} diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/valkyrie.h linux/drivers/macintosh/valkyrie.h --- v2.1.50/linux/drivers/macintosh/valkyrie.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/valkyrie.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,17 @@ +/* + * Exported procedures for the "valkyrie" display driver on PowerMacs. + * + * Copyright (C) 1997 Paul Mackerras. + * + * 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. + */ + +extern void map_valkyrie_display(struct device_node *); +extern void valkyrie_init(void); +extern int valkyrie_setmode(struct vc_mode *mode, int doit); +extern void valkyrie_set_palette(unsigned char red[], unsigned char green[], + unsigned char blue[], int index, int ncolors); +extern void valkyrie_set_blanking(int blank_mode); diff -u --recursive --new-file v2.1.50/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c --- v2.1.50/linux/drivers/macintosh/via-cuda.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/macintosh/via-cuda.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,415 @@ +/* + * Device driver for the via-cuda on Apple Powermacs. + * + * The VIA (versatile interface adapter) interfaces to the CUDA, + * a 6805 microprocessor core which controls the ADB (Apple Desktop + * Bus) which connects to the keyboard and mouse. The CUDA also + * controls system power and the RTC (real time clock) chip. + * + * This file also contains routines to support access to ADB + * devices via the /dev/adb interface. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile unsigned char *via; + +/* VIA registers - spaced 0x200 bytes apart */ +#define RS 0x200 /* skip between registers */ +#define B 0 /* B-side data */ +#define A RS /* A-side data */ +#define DIRB (2*RS) /* B-side direction (1=output) */ +#define DIRA (3*RS) /* A-side direction (1=output) */ +#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ +#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ +#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ +#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ +#define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ +#define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ +#define SR (10*RS) /* Shift register */ +#define ACR (11*RS) /* Auxiliary control register */ +#define PCR (12*RS) /* Peripheral control register */ +#define IFR (13*RS) /* Interrupt flag register */ +#define IER (14*RS) /* Interrupt enable register */ +#define ANH (15*RS) /* A-side data, no handshake */ + +/* Bits in B data register: all active low */ +#define TREQ 0x08 /* Transfer request (input) */ +#define TACK 0x10 /* Transfer acknowledge (output) */ +#define TIP 0x20 /* Transfer in progress (output) */ + +/* Bits in ACR */ +#define SR_CTRL 0x1c /* Shift register control bits */ +#define SR_EXT 0x0c /* Shift on external clock */ +#define SR_OUT 0x10 /* Shift out if 1 */ + +/* Bits in IFR and IER */ +#define IER_SET 0x80 /* set bits in IER */ +#define IER_CLR 0 /* clear bits in IER */ +#define SR_INT 0x04 /* Shift register full/empty */ + +static struct adb_handler { + void (*handler)(unsigned char *, int, struct pt_regs *); +} adb_handler[16]; + +static enum cuda_state { + idle, + sent_first_byte, + sending, + reading, + read_done, + awaiting_reply +} cuda_state; + +static struct cuda_request *current_req; +static struct cuda_request *last_req; +static unsigned char cuda_rbuf[16]; +static unsigned char *reply_ptr; +static int reading_reply; +static int data_index; + +static int init_via(void); +static void cuda_start(void); +static void via_interrupt(int irq, void *arg, struct pt_regs *regs); +static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs); + +void +via_cuda_init() +{ + struct device_node *vias; + + vias = find_devices("via-cuda"); + if (vias == 0) { + printk(KERN_WARNING "Warning: no via-cuda\n"); + vias = find_devices("via-pmu"); + if (vias == 0) + return; + printk(KERN_WARNING "Found via-pmu, using it as via-cuda\n"); + } + if (vias->next != 0) + printk("Warning: only using 1st via-cuda\n"); + +#if 0 + { int i; + + printk("via_cuda_init: node = %p, addrs =", vias->node); + for (i = 0; i < vias->n_addrs; ++i) + printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size); + printk(", intrs ="); + for (i = 0; i < vias->n_intrs; ++i) + printk(" %x", vias->intrs[i]); + printk("\n"); } +#endif + + if (vias->n_addrs != 1 || vias->n_intrs != 1) + panic("via-cuda: expecting 1 address and 1 interrupt"); + via = (volatile unsigned char *) vias->addrs->address; + + if (!init_via()) + panic("init_via failed"); + + cuda_state = idle; + + if (request_irq(vias->intrs[0], via_interrupt, 0, "VIA", (void *)0)) + panic("VIA: can't get irq %d\n", vias->intrs[0]); + + /* Clear and enable interrupts */ + via[IFR] = 0x7f; eieio(); /* clear interrupts by writing 1s */ + via[IER] = IER_SET|SR_INT; eieio(); /* enable interrupt from SR */ +} + +#define WAIT_FOR(cond, what) \ + do { \ + for (x = 1000; !(cond); --x) { \ + if (x == 0) { \ + printk("Timeout waiting for " what); \ + return 0; \ + } \ + udelay(100); \ + } \ + } while (0) + +static int +init_via() +{ + int x; + + via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; /* TACK & TIP out */ + via[B] |= TACK | TIP; /* negate them */ + via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; /* SR data in */ + eieio(); + x = via[SR]; eieio(); /* clear any left-over data */ + via[IER] = 0x7f; eieio(); /* disable interrupts from VIA */ + eieio(); + + /* delay 4ms and then clear any pending interrupt */ + udelay(4000); + x = via[SR]; eieio(); + + /* sync with the CUDA - assert TACK without TIP */ + via[B] &= ~TACK; eieio(); + + /* wait for the CUDA to assert TREQ in response */ + WAIT_FOR((via[B] & TREQ) == 0, "CUDA response to sync"); + + /* wait for the interrupt and then clear it */ + WAIT_FOR(via[IFR] & SR_INT, "CUDA response to sync (2)"); + x = via[SR]; eieio(); + + /* finish the sync by negating TACK */ + via[B] |= TACK; eieio(); + + /* wait for the CUDA to negate TREQ and the corresponding interrupt */ + WAIT_FOR(via[B] & TREQ, "CUDA response to sync (3)"); + WAIT_FOR(via[IFR] & SR_INT, "CUDA response to sync (4)"); + x = via[SR]; eieio(); + via[B] |= TIP; eieio(); /* should be unnecessary */ + + return 1; +} + +/* Construct and send a cuda request */ +int +cuda_request(struct cuda_request *req, void (*done)(struct cuda_request *), + int nbytes, ...) +{ + va_list list; + int i; + + req->nbytes = nbytes; + req->done = done; + va_start(list, nbytes); + for (i = 0; i < nbytes; ++i) + req->data[i] = va_arg(list, int); + va_end(list); + req->reply_expected = 1; + return cuda_send_request(req); +} + +int +cuda_send_request(struct cuda_request *req) +{ + unsigned long flags; + + req->next = 0; + req->sent = 0; + req->got_reply = 0; + req->reply_len = 0; + save_flags(flags); cli(); + + if (current_req != 0) { + last_req->next = req; + last_req = req; + } else { + current_req = req; + last_req = req; + if (cuda_state == idle) + cuda_start(); + } + + restore_flags(flags); + return 0; +} + +static void +cuda_start() +{ + unsigned long flags; + struct cuda_request *req; + + /* assert cuda_state == idle */ + /* get the packet to send */ + req = current_req; + if (req == 0) + return; + save_flags(flags); cli(); + if ((via[B] & TREQ) == 0) { + restore_flags(flags); + return; /* a byte is coming in from the CUDA */ + } + + /* set the shift register to shift out and send a byte */ + via[ACR] |= SR_OUT; eieio(); + via[SR] = req->data[0]; eieio(); + via[B] &= ~TIP; + cuda_state = sent_first_byte; + restore_flags(flags); +} + +void +cuda_poll() +{ + int ie; + + ie = _disable_interrupts(); + if (via[IFR] & SR_INT) + via_interrupt(0, 0, 0); + _enable_interrupts(ie); +} + +static void +via_interrupt(int irq, void *arg, struct pt_regs *regs) +{ + int x, status; + struct cuda_request *req; + + if ((via[IFR] & SR_INT) == 0) + return; + + status = (~via[B] & (TIP|TREQ)) | (via[ACR] & SR_OUT); eieio(); + /* printk("via_interrupt: state=%d status=%x\n", cuda_state, status); */ + switch (cuda_state) { + case idle: + /* CUDA has sent us the first byte of data - unsolicited */ + if (status != TREQ) + printk("cuda: state=idle, status=%x\n", status); + x = via[SR]; eieio(); + via[B] &= ~TIP; eieio(); + cuda_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + break; + + case awaiting_reply: + /* CUDA has sent us the first byte of data of a reply */ + if (status != TREQ) + printk("cuda: state=awaiting_reply, status=%x\n", status); + x = via[SR]; eieio(); + via[B] &= ~TIP; eieio(); + cuda_state = reading; + reply_ptr = current_req->reply; + reading_reply = 1; + break; + + case sent_first_byte: + if (status == TREQ + TIP + SR_OUT) { + /* collision */ + via[ACR] &= ~SR_OUT; eieio(); + x = via[SR]; eieio(); + via[B] |= TIP | TACK; eieio(); + cuda_state = idle; + } else { + /* assert status == TIP + SR_OUT */ + if (status != TIP + SR_OUT) + printk("cuda: state=sent_first_byte status=%x\n", status); + via[SR] = current_req->data[1]; eieio(); + via[B] ^= TACK; eieio(); + data_index = 2; + cuda_state = sending; + } + break; + + case sending: + req = current_req; + if (data_index >= req->nbytes) { + via[ACR] &= ~SR_OUT; eieio(); + x = via[SR]; eieio(); + via[B] |= TACK | TIP; eieio(); + req->sent = 1; + if (req->reply_expected) { + cuda_state = awaiting_reply; + } else { + current_req = req->next; + if (req->done) + (*req->done)(req); + /* not sure about this */ + cuda_state = idle; + cuda_start(); + } + } else { + via[SR] = req->data[data_index++]; eieio(); + via[B] ^= TACK; eieio(); + } + break; + + case reading: + *reply_ptr++ = via[SR]; eieio(); + if (status == TIP) { + /* that's all folks */ + via[B] |= TACK | TIP; eieio(); + cuda_state = read_done; + } else { + /* assert status == TIP | TREQ */ + if (status != TIP + TREQ) + printk("cuda: state=reading status=%x\n", status); + via[B] ^= TACK; eieio(); + } + break; + + case read_done: + x = via[SR]; eieio(); + if (reading_reply) { + req = current_req; + req->reply_len = reply_ptr - req->reply; + req->got_reply = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); + } else { + cuda_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs); + } + if (status == TREQ) { + via[B] &= ~TIP; eieio(); + cuda_state = reading; + reply_ptr = cuda_rbuf; + reading_reply = 0; + } else { + cuda_state = idle; + cuda_start(); + } + break; + + default: + printk("via_interrupt: unknown cuda_state %d?\n", cuda_state); + } +} + +static void +cuda_input(unsigned char *buf, int nb, struct pt_regs *regs) +{ + int i, id; + static int dump_cuda_input = 0; + + switch (buf[0]) { + case ADB_PACKET: + id = buf[2] >> 4; + if (dump_cuda_input) { + printk(KERN_INFO "adb packet: "); + for (i = 0; i < nb; ++i) + printk(" %x", buf[i]); + printk(", id = %d\n", id); + } + if (adb_handler[id].handler != 0) { + (*adb_handler[id].handler)(buf, nb, regs); + } + break; + + default: + printk("data from cuda (%d bytes):", nb); + for (i = 0; i < nb; ++i) + printk(" %.2x", buf[i]); + printk("\n"); + } +} + +/* Ultimately this should return the number of devices with + the given default id. */ +int +adb_register(int default_id, + void (*handler)(unsigned char *, int, struct pt_regs *)) +{ + if (adb_handler[default_id].handler != 0) + panic("Two handlers for ADB device %d\n", default_id); + adb_handler[default_id].handler = handler; + return 1; +} diff -u --recursive --new-file v2.1.50/linux/drivers/net/mace.c linux/drivers/net/mace.c --- v2.1.50/linux/drivers/net/mace.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/mace.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,800 @@ +/* + * Network device driver for the MACE ethernet controller on + * Apple Powermacs. Assumes it's under a DBDMA controller. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mace.h" + +#define N_RX_RING 8 +#define N_TX_RING 6 +#define MAX_TX_ACTIVE 1 +#define NCMDS_TX 1 /* dma commands per element in tx ring */ +#define RX_BUFLEN (ETH_FRAME_LEN + 8) +#define TX_TIMEOUT HZ /* 1 second */ + +/* Bits in transmit DMA status */ +#define TX_DMA_ERR 0x80 + +struct mace_data { + volatile struct mace *mace; + volatile struct dbdma_regs *tx_dma; + int tx_dma_intr; + volatile struct dbdma_regs *rx_dma; + int rx_dma_intr; + volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */ + volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */ + struct sk_buff *rx_bufs[N_RX_RING]; + int rx_fill; + int rx_empty; + struct sk_buff *tx_bufs[N_TX_RING]; + int tx_fill; + int tx_empty; + unsigned char maccc; + unsigned char tx_fullup; + unsigned char tx_active; + unsigned char tx_bad_runt; + struct net_device_stats stats; + struct timer_list tx_timeout; +}; + +/* + * Number of bytes of private data per MACE: allow enough for + * the rx and tx dma commands plus a branch dma command each, + * and another 16 bytes to allow us to align the dma command + * buffers on a 16 byte boundary. + */ +#define PRIV_BYTES (sizeof(struct mace_data) \ + + (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd)) + +static int bitrev(int); +static int mace_open(struct device *dev); +static int mace_close(struct device *dev); +static int mace_xmit_start(struct sk_buff *skb, struct device *dev); +static struct net_device_stats *mace_stats(struct device *dev); +static void mace_set_multicast(struct device *dev); +static void mace_reset(struct device *dev); +static int mace_set_address(struct device *dev, void *addr); +static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static void mace_set_timeout(struct device *dev); +static void mace_tx_timeout(unsigned long data); + +/* + * If we can't get a skbuff when we need it, we use this area for DMA. + */ +static unsigned char dummy_buf[RX_BUFLEN+2]; + +/* Bit-reverse one byte of an ethernet hardware address. */ +static int +bitrev(int b) +{ + int d = 0, i; + + for (i = 0; i < 8; ++i, b >>= 1) + d = (d << 1) | (b & 1); + return d; +} + +int +mace_probe(struct device *dev) +{ + int j, rev; + struct mace_data *mp; + struct device_node *maces; + unsigned char *addr; + + maces = find_devices("mace"); + if (maces == 0) + return ENODEV; + + do { + if (maces->n_addrs != 3 || maces->n_intrs != 3) { + printk(KERN_ERR "can't use MACE %s: expect 3 addrs and 3 intrs\n", + maces->full_name); + continue; + } + + if (dev == NULL) + dev = init_etherdev(0, PRIV_BYTES); + else { + /* XXX this doesn't look right (but it's never used :-) */ + dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL); + if (dev->priv == 0) + return -ENOMEM; + } + + mp = (struct mace_data *) dev->priv; + dev->base_addr = maces->addrs[0].address; + mp->mace = (volatile struct mace *) maces->addrs[0].address; + dev->irq = maces->intrs[0]; + + 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(maces->intrs[1], mace_txdma_intr, 0, "MACE-txdma", + dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[1]); + return -EAGAIN; + } + if (request_irq(maces->intrs[2], mace_rxdma_intr, 0, "MACE-rxdma", + dev)) { + printk(KERN_ERR "MACE: can't get irq %d\n", maces->intrs[2]); + return -EAGAIN; + } + + addr = get_property(maces, "mac-address", NULL); + if (addr == NULL) { + addr = get_property(maces, "local-mac-address", NULL); + if (addr == NULL) { + printk(KERN_ERR "Can't get mac-address for MACE at %lx\n", + dev->base_addr); + return -EAGAIN; + } + } + + printk(KERN_INFO "%s: MACE at", dev->name); + rev = addr[0] == 0 && addr[1] == 0xA0; + for (j = 0; j < 6; ++j) { + dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j]; + printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]); + } + printk("\n"); + + mp = (struct mace_data *) dev->priv; + mp->maccc = ENXMT | ENRCV; + mp->tx_dma = (volatile struct dbdma_regs *) maces->addrs[1].address; + mp->tx_dma_intr = maces->intrs[1]; + mp->rx_dma = (volatile struct dbdma_regs *) maces->addrs[2].address; + mp->rx_dma_intr = maces->intrs[2]; + + mp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(mp + 1); + mp->rx_cmds = mp->tx_cmds + NCMDS_TX * N_TX_RING + 1; + + memset(&mp->stats, 0, sizeof(mp->stats)); + memset((char *) mp->tx_cmds, 0, + (NCMDS_TX*N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); + + mace_reset(dev); + + dev->open = mace_open; + dev->stop = mace_close; + dev->hard_start_xmit = mace_xmit_start; + dev->get_stats = mace_stats; + dev->set_multicast_list = mace_set_multicast; + dev->set_mac_address = mace_set_address; + + ether_setup(dev); + + } while ((maces = maces->next) != 0); + + return 0; +} + +static void mace_reset(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i; + + /* soft-reset the chip */ + mb->biucc = SWRST; eieio(); + udelay(100); + + 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->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */ + + /* load up the hardware address */ + mb->iac = ADDRCHG | PHYADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 6; ++i) { + mb->padr = dev->dev_addr[i]; + eieio(); + } + + /* clear the multicast filter */ + mb->iac = ADDRCHG | LOGADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 8; ++i) { + mb->ladrf = 0; + eieio(); + } + + mb->plscc = PORTSEL_GPSI + ENPLSIO; +} + +static int mace_set_address(struct device *dev, void *addr) +{ + unsigned char *p = addr; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i; + unsigned long flags; + + save_flags(flags); cli(); + + /* load up the hardware address */ + mb->iac = ADDRCHG | PHYADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 6; ++i) { + mb->padr = dev->dev_addr[i] = p[i]; + eieio(); + } + /* note: setting ADDRCHG clears ENRCV */ + mb->maccc = mp->maccc; eieio(); + + restore_flags(flags); + return 0; +} + +static int mace_open(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_cmd *cp; + int i; + struct sk_buff *skb; + unsigned char *data; + + /* initialize list of sk_buffs for receiving and set up recv dma */ + memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd)); + cp = mp->rx_cmds; + for (i = 0; i < N_RX_RING - 1; ++i) { + skb = dev_alloc_skb(RX_BUFLEN + 2); + if (skb == 0) { + data = dummy_buf; + } else { + skb_reserve(skb, 2); /* so IP header lands on 4-byte bdry */ + data = skb->data; + } + mp->rx_bufs[i] = skb; + st_le16(&cp->req_count, RX_BUFLEN); + st_le16(&cp->command, INPUT_LAST + INTR_ALWAYS); + st_le32(&cp->phy_addr, virt_to_bus(data)); + cp->xfer_status = 0; + ++cp; + } + mp->rx_bufs[i] = 0; + st_le16(&cp->command, DBDMA_STOP); + mp->rx_fill = i; + mp->rx_empty = 0; + + /* Put a branch back to the beginning of the receive command list */ + ++cp; + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(mp->rx_cmds)); + + /* start rx dma */ + out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + out_le32(&rd->cmdptr, virt_to_bus(mp->rx_cmds)); + out_le32(&rd->control, (RUN << 16) | RUN); + + /* put a branch at the end of the tx command list */ + cp = mp->tx_cmds + NCMDS_TX * N_TX_RING; + st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); + st_le32(&cp->cmd_dep, virt_to_bus(mp->tx_cmds)); + + /* reset tx dma */ + out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le32(&td->cmdptr, virt_to_bus(mp->tx_cmds)); + mp->tx_fill = 0; + mp->tx_empty = 0; + mp->tx_fullup = 0; + mp->tx_active = 0; + mp->tx_bad_runt = 0; + + /* turn it on! */ + mb->maccc = mp->maccc; eieio(); + /* enable all interrupts except receive interrupts */ + mb->imr = RCVINT; eieio(); + return 0; +} + +static int mace_close(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_regs *td = mp->tx_dma; + int i; + + /* disable rx and tx */ + mb->maccc = 0; + mb->imr = 0xff; /* disable all intrs */ + + /* disable rx and tx dma */ + st_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + st_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + + /* free some skb's */ + for (i = 0; i < N_RX_RING; ++i) { + if (mp->rx_bufs[i] != 0) { + dev_kfree_skb(mp->rx_bufs[i], FREE_READ); + mp->rx_bufs[i] = 0; + } + } + for (i = mp->tx_empty; i != mp->tx_fill; ) { + dev_kfree_skb(mp->tx_bufs[i], FREE_WRITE); + if (++i >= N_TX_RING) + i = 0; + } + + return 0; +} + +static inline void mace_set_timeout(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + + mp->tx_timeout.expires = jiffies + TX_TIMEOUT; + mp->tx_timeout.function = mace_tx_timeout; + mp->tx_timeout.data = (unsigned long) dev; + add_timer(&mp->tx_timeout); +} + +static int mace_xmit_start(struct sk_buff *skb, struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_cmd *cp, *np; + unsigned long flags; + int fill, next, len; + + /* see if there's a free slot in the tx ring */ + save_flags(flags); cli(); + fill = mp->tx_fill; + next = fill + 1; + if (next >= N_TX_RING) + next = 0; + if (next == mp->tx_empty) { + dev->tbusy = 1; + mp->tx_fullup = 1; + restore_flags(flags); + return -1; /* can't take it at the moment */ + } + restore_flags(flags); + + /* partially fill in the dma command block */ + len = skb->len; + if (len > ETH_FRAME_LEN) { + printk(KERN_DEBUG "mace: xmit frame too long (%d)\n", len); + len = ETH_FRAME_LEN; + } + mp->tx_bufs[fill] = skb; + cp = mp->tx_cmds + NCMDS_TX * fill; + st_le16(&cp->req_count, len); + st_le32(&cp->phy_addr, virt_to_bus(skb->data)); + + np = mp->tx_cmds + NCMDS_TX * next; + out_le16(&np->command, DBDMA_STOP); + + /* poke the tx dma channel */ + save_flags(flags); + cli(); + mp->tx_fill = next; + if (!mp->tx_bad_runt && mp->tx_active < MAX_TX_ACTIVE) { + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, OUTPUT_LAST); + out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + ++mp->tx_active; + mace_set_timeout(dev); + } + restore_flags(flags); + + return 0; +} + +static struct net_device_stats *mace_stats(struct device *dev) +{ + struct mace_data *p = (struct mace_data *) dev->priv; + + return &p->stats; +} + +/* + * CRC polynomial - used in working out multicast filter bits. + */ +#define CRC_POLY 0xedb88320 + +static void mace_set_multicast(struct device *dev) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i, j, k, b; + unsigned long crc; + + mp->maccc &= ~PROM; + if (dev->flags & IFF_PROMISC) { + mp->maccc |= PROM; + } else { + unsigned char multicast_filter[8]; + struct dev_mc_list *dmi = dev->mc_list; + + if (dev->flags & IFF_ALLMULTI) { + for (i = 0; i < 8; i++) + multicast_filter[i] = 0xff; + } else { + for (i = 0; i < 8; i++) + multicast_filter[i] = 0; + for (i = 0; i < dev->mc_count; i++) { + crc = ~0; + for (j = 0; j < 6; ++j) { + b = dmi->dmi_addr[j]; + for (k = 0; k < 8; ++k) { + if ((crc ^ b) & 1) + crc = (crc >> 1) ^ CRC_POLY; + else + crc >>= 1; + b >>= 1; + } + } + j = crc >> 26; /* bit number in multicast_filter */ + multicast_filter[j >> 3] |= 1 << (j & 7); + dmi = dmi->next; + } + } +#if 0 + printk("Multicast filter :"); + for (i = 0; i < 8; i++) + printk("%02x ", multicast_filter[i]); + printk("\n"); +#endif + + mb->iac = ADDRCHG | LOGADDR; eieio(); + while ((mb->iac & ADDRCHG) != 0) + eieio(); + for (i = 0; i < 8; ++i) { + mb->ladrf = multicast_filter[i]; + eieio(); + } + } + /* reset maccc */ + mb->maccc = mp->maccc; eieio(); +} + +static void mace_handle_misc_intrs(struct mace_data *mp, int intr) +{ + volatile struct mace *mb = mp->mace; + static int mace_babbles, mace_jabbers; + + if (intr & MPCO) + mp->stats.rx_missed_errors += 256; + mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */ + if (intr & RNTPCO) + mp->stats.rx_length_errors += 256; + mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */ + if (intr & CERR) + ++mp->stats.tx_heartbeat_errors; + if (intr & BABBLE) + if (mace_babbles++ < 4) + printk(KERN_DEBUG "mace: babbling transmitter\n"); + if (intr & JABBER) + if (mace_jabbers++ < 4) + printk(KERN_DEBUG "mace: jabbering transceiver\n"); +} + +static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_cmd *cp; + int intr, fs, i, stat, x; + int xcount, dstat; + static int mace_last_fs, mace_last_xcount; + + intr = mb->ir; /* read interrupt register */ + mace_handle_misc_intrs(mp, intr); + + i = mp->tx_empty; + while (mb->pr & XMTSV) { + /* + * Clear any interrupt indication associated with this status + * word. This appears to unlatch any error indication from + * the DMA controller. + */ + intr = mb->ir; + if (intr != 0) + mace_handle_misc_intrs(mp, intr); + if (mp->tx_bad_runt) { + fs = mb->xmtfs; + eieio(); + mp->tx_bad_runt = 0; + mb->xmtfc = AUTO_PAD_XMIT; + del_timer(&mp->tx_timeout); + continue; + } + dstat = ld_le32(&td->status); + /* stop DMA controller */ + out_le32(&td->control, RUN << 16); + /* + * xcount is the number of complete frames which have been + * written to the fifo but for which status has not been read. + */ + xcount = (mb->fifofc >> XMTFC_SH) & XMTFC_MASK; + if (xcount == 0 || (dstat & DEAD)) { + /* + * If a packet was aborted before the DMA controller has + * finished transferring it, it seems that there are 2 bytes + * which are stuck in some buffer somewhere. These will get + * transmitted as soon as we read the frame status (which + * reenables the transmit data transfer request). Turning + * off the DMA controller and/or resetting the MACE doesn't + * help. So we disable auto-padding and FCS transmission + * so the two bytes will only be a runt packet which should + * be ignored by other stations. + */ + mb->xmtfc = DXMTFCS; + eieio(); + } + fs = mb->xmtfs; + if ((fs & XMTSV) == 0) { + printk(KERN_ERR "mace: xmtfs not valid! (fs=%x xc=%d ds=%x)\n", fs, xcount, dstat); + } + cp = mp->tx_cmds + NCMDS_TX * i; + stat = ld_le16(&cp->xfer_status); + if ((fs & (UFLO|LCOL|LCAR|RTRY)) || (dstat & DEAD) || xcount == 0) { + /* + * Check whether there were in fact 2 bytes written to + * the transmit FIFO. + */ + x = (mb->fifofc >> XMTFC_SH) & XMTFC_MASK; + if (x != 0) { + /* there were two bytes with an end-of-packet indication */ + mp->tx_bad_runt = 1; + mace_set_timeout(dev); + } else { + /* + * Either there weren't the two bytes buffered up, or they + * didn't have an end-of-packet indication. Maybe we ought + * to flush the transmit FIFO just in case (by setting the + * XMTFWU bit with the transmitter disabled). + */ + mb->xmtfc = AUTO_PAD_XMIT; + eieio(); + } + } + /* dma should have finished */ + if (i == mp->tx_fill) { + printk(KERN_DEBUG "mace: tx ring ran out? (fs=%x xc=%d ds=%x)\n", fs, xcount, dstat); + continue; + } + /* Update stats */ + if (fs & (UFLO|LCOL|LCAR|RTRY)) { + ++mp->stats.tx_errors; + if (fs & LCAR) + ++mp->stats.tx_carrier_errors; + if (fs & (UFLO|LCOL|RTRY)) + ++mp->stats.tx_aborted_errors; + } else + ++mp->stats.tx_packets; + dev_kfree_skb(mp->tx_bufs[i], FREE_WRITE); + --mp->tx_active; + if (++i >= N_TX_RING) + i = 0; + mace_last_fs = fs; + mace_last_xcount = xcount; + del_timer(&mp->tx_timeout); + } + + mp->tx_empty = i; + i += mp->tx_active; + if (i >= N_TX_RING) + i -= N_TX_RING; + if (i != mp->tx_fill && mp->tx_fullup) { + mp->tx_fullup = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (!mp->tx_bad_runt && i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE) { + do { + /* set up the next one */ + cp = mp->tx_cmds + NCMDS_TX * i; + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, OUTPUT_LAST); + ++mp->tx_active; + if (++i >= N_TX_RING) + i = 0; + } while (i != mp->tx_fill && mp->tx_active < MAX_TX_ACTIVE); + out_le32(&td->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); + mace_set_timeout(dev); + } +} + +static void mace_tx_timeout(unsigned long data) +{ + struct device *dev = (struct device *) data; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + volatile struct dbdma_regs *td = mp->tx_dma; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_cmd *cp; + unsigned long flags; + int i; + + save_flags(flags); + cli(); + if (mp->tx_active == 0 && !mp->tx_bad_runt) + goto out; + + /* update various counters */ + mace_handle_misc_intrs(mp, mb->ir); + + cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty; + printk(KERN_DEBUG "mace: tx dmastat=%x %x bad_runt=%d pr=%x fs=%x fc=%x\n", + ld_le32(&td->status), ld_le16(&cp->xfer_status), mp->tx_bad_runt, + mb->pr, mb->xmtfs, mb->fifofc); + + /* turn off both tx and rx and reset the chip */ + mb->maccc = 0; + out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + printk(KERN_ERR "mace: transmit timeout - resetting\n"); + mace_reset(dev); + + /* restart rx dma */ + cp = bus_to_virt(ld_le32(&rd->cmdptr)); + out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + out_le16(&cp->xfer_status, 0); + out_le32(&rd->cmdptr, virt_to_bus(cp)); + out_le32(&rd->control, (RUN << 16) | RUN); + + /* fix up the transmit side */ + i = mp->tx_empty; + mp->tx_active = 0; + ++mp->stats.tx_errors; + if (mp->tx_bad_runt) { + mp->tx_bad_runt = 0; + } else if (i != mp->tx_fill) { + dev_kfree_skb(mp->tx_bufs[i], FREE_WRITE); + if (++i >= N_TX_RING) + i = 0; + mp->tx_empty = i; + } + if (mp->tx_fullup) { + mp->tx_fullup = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (i != mp->tx_fill) { + cp = mp->tx_cmds + NCMDS_TX * i; + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, OUTPUT_LAST); + out_le32(&td->cmdptr, virt_to_bus(cp)); + out_le32(&td->control, (RUN << 16) | RUN); + ++mp->tx_active; + mace_set_timeout(dev); + } + + /* turn it back on */ + out_8(&mb->imr, RCVINT); + out_8(&mb->maccc, mp->maccc); + +out: + restore_flags(flags); +} + +static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct dbdma_regs *rd = mp->rx_dma; + volatile struct dbdma_cmd *cp, *np; + int i, nb, stat, next; + struct sk_buff *skb; + unsigned frame_status; + static int mace_lost_status; + unsigned char *data; + + for (i = mp->rx_empty; i != mp->rx_fill; ) { + cp = mp->rx_cmds + i; + stat = ld_le16(&cp->xfer_status); + if ((stat & ACTIVE) == 0) { + next = i + 1; + if (next >= N_RX_RING) + next = 0; + np = mp->rx_cmds + next; + if (next != mp->rx_fill + && (ld_le16(&np->xfer_status) & ACTIVE) != 0) { + printk(KERN_DEBUG "mace: lost a status word\n"); + ++mace_lost_status; + } else + break; + } + nb = ld_le16(&cp->req_count) - ld_le16(&cp->res_count); + out_le16(&cp->command, DBDMA_STOP); + /* got a packet, have a look at it */ + skb = mp->rx_bufs[i]; + if (skb == 0) { + ++mp->stats.rx_dropped; + } else if (nb > 8) { + data = skb->data; + frame_status = (data[nb-3] << 8) + data[nb-4]; + if (frame_status & (RS_OFLO|RS_CLSN|RS_FRAMERR|RS_FCSERR)) { + ++mp->stats.rx_errors; + if (frame_status & RS_OFLO) + ++mp->stats.rx_over_errors; + if (frame_status & RS_FRAMERR) + ++mp->stats.rx_frame_errors; + if (frame_status & RS_FCSERR) + ++mp->stats.rx_crc_errors; + } else { + nb -= 8; + skb_put(skb, nb); + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + mp->rx_bufs[i] = 0; + ++mp->stats.rx_packets; + } + } else { + ++mp->stats.rx_errors; + ++mp->stats.rx_length_errors; + } + + /* advance to next */ + if (++i >= N_RX_RING) + i = 0; + } + mp->rx_empty = i; + + i = mp->rx_fill; + for (;;) { + next = i + 1; + if (next >= N_RX_RING) + next = 0; + if (next == mp->rx_empty) + break; + cp = mp->rx_cmds + i; + skb = mp->rx_bufs[i]; + if (skb == 0) { + skb = dev_alloc_skb(RX_BUFLEN + 2); + if (skb != 0) { + skb_reserve(skb, 2); + mp->rx_bufs[i] = skb; + } + } + st_le16(&cp->req_count, RX_BUFLEN); + data = skb? skb->data: dummy_buf; + st_le32(&cp->phy_addr, virt_to_bus(data)); + out_le16(&cp->xfer_status, 0); + out_le16(&cp->command, INPUT_LAST + INTR_ALWAYS); +#if 0 + if ((ld_le32(&rd->status) & ACTIVE) != 0) { + out_le32(&rd->control, (PAUSE << 16) | PAUSE); + while ((in_le32(&rd->status) & ACTIVE) != 0) + ; + } +#endif + i = next; + } + if (i != mp->rx_fill) { + out_le32(&rd->control, ((RUN|WAKE) << 16) | (RUN|WAKE)); + mp->rx_fill = i; + } +} diff -u --recursive --new-file v2.1.50/linux/drivers/net/mace.h linux/drivers/net/mace.h --- v2.1.50/linux/drivers/net/mace.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/mace.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,173 @@ +/* + * mace.h - definitions for the registers in the Am79C940 MACE + * (Medium Access Control for Ethernet) controller. + * + * Copyright (C) 1996 Paul Mackerras. + * + * 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. + */ + +#define REG(x) volatile unsigned char x; char x ## _pad[15] + +struct mace { + REG(rcvfifo); /* receive FIFO */ + REG(xmtfifo); /* transmit FIFO */ + REG(xmtfc); /* transmit frame control */ + REG(xmtfs); /* transmit frame status */ + REG(xmtrc); /* transmit retry count */ + REG(rcvfc); /* receive frame control */ + REG(rcvfs); /* receive frame status (4 bytes) */ + REG(fifofc); /* FIFO frame count */ + REG(ir); /* interrupt register */ + REG(imr); /* interrupt mask register */ + REG(pr); /* poll register */ + REG(biucc); /* bus interface unit config control */ + REG(fifocc); /* FIFO configuration control */ + REG(maccc); /* medium access control config control */ + REG(plscc); /* phys layer signalling config control */ + REG(phycc); /* physical configuration control */ + REG(chipid_lo); /* chip ID, lsb */ + REG(chipid_hi); /* chip ID, msb */ + REG(iac); /* internal address config */ + REG(reg19); + REG(ladrf); /* logical address filter (8 bytes) */ + REG(padr); /* physical address (6 bytes) */ + REG(reg22); + REG(reg23); + REG(mpc); /* missed packet count (clears when read) */ + REG(reg25); + REG(rntpc); /* runt packet count (clears when read) */ + REG(rcvcc); /* recv collision count (clears when read) */ + REG(reg28); + REG(utr); /* user test reg */ + REG(reg30); + REG(reg31); +}; + +/* Bits in XMTFC */ +#define DRTRY 0x80 /* don't retry transmission after collision */ +#define DXMTFCS 0x08 /* don't append FCS to transmitted frame */ +#define AUTO_PAD_XMIT 0x01 /* auto-pad short packets on transmission */ + +/* Bits in XMTFS: only valid when XMTSV is set in PR and XMTFS */ +#define XMTSV 0x80 /* transmit status (i.e. XMTFS) valid */ +#define UFLO 0x40 /* underflow - xmit fifo ran dry */ +#define LCOL 0x20 /* late collision (transmission aborted) */ +#define MORE 0x10 /* 2 or more retries needed to xmit frame */ +#define ONE 0x08 /* 1 retry needed to xmit frame */ +#define DEFER 0x04 /* MACE had to defer xmission (enet busy) */ +#define LCAR 0x02 /* loss of carrier (transmission aborted) */ +#define RTRY 0x01 /* too many retries (transmission aborted) */ + +/* Bits in XMTRC: only valid when XMTSV is set in PR (and XMTFS) */ +#define EXDEF 0x80 /* had to defer for excessive time */ +#define RETRY_MASK 0x0f /* number of retries (0 - 15) */ + +/* Bits in RCVFC */ +#define LLRCV 0x08 /* low latency receive: early DMA request */ +#define M_RBAR 0x04 /* sets function of EAM/R pin */ +#define AUTO_STRIP_RCV 0x01 /* auto-strip short LLC frames on recv */ + +/* + * Bits in RCVFS. After a frame is received, four bytes of status + * are automatically read from this register and appended to the frame + * data in memory. These are: + * Byte 0 and 1: message byte count and frame status + * Byte 2: runt packet count + * Byte 3: receive collision count + */ +#define RS_OFLO 0x8000 /* receive FIFO overflowed */ +#define RS_CLSN 0x4000 /* received frame suffered (late) collision */ +#define RS_FRAMERR 0x2000 /* framing error flag */ +#define RS_FCSERR 0x1000 /* frame had FCS error */ +#define RS_COUNT 0x0fff /* mask for byte count field */ + +/* Bits (fields) in FIFOFC */ +#define RCVFC_SH 4 /* receive frame count in FIFO */ +#define RCVFC_MASK 0x0f +#define XMTFC_SH 0 /* transmit frame count in FIFO */ +#define XMTFC_MASK 0x0f + +/* + * Bits in IR and IMR. The IR clears itself when read. + * Setting a bit in the IMR will disable the corresponding interrupt. + */ +#define JABBER 0x80 /* jabber error - 10baseT xmission too long */ +#define BABBLE 0x40 /* babble - xmitter xmitting for too long */ +#define CERR 0x20 /* collision err - no SQE test (heartbeat) */ +#define RCVCCO 0x10 /* RCVCC overflow */ +#define RNTPCO 0x08 /* RNTPC overflow */ +#define MPCO 0x04 /* MPC overflow */ +#define RCVINT 0x02 /* receive interrupt */ +#define XMTINT 0x01 /* transmitter interrupt */ + +/* Bits in PR */ +#define XMTSV 0x80 /* XMTFS valid (same as in XMTFS) */ +#define TDTREQ 0x40 /* set when xmit fifo is requesting data */ +#define RDTREQ 0x20 /* set when recv fifo requests data xfer */ + +/* Bits in BIUCC */ +#define BSWP 0x40 /* byte swap, i.e. big-endian bus */ +#define XMTSP_4 0x00 /* start xmitting when 4 bytes in FIFO */ +#define XMTSP_16 0x10 /* start xmitting when 16 bytes in FIFO */ +#define XMTSP_64 0x20 /* start xmitting when 64 bytes in FIFO */ +#define XMTSP_112 0x30 /* start xmitting when 112 bytes in FIFO */ +#define SWRST 0x01 /* software reset */ + +/* Bits in FIFOCC */ +#define XMTFW_8 0x00 /* xmit fifo watermark = 8 words free */ +#define XMTFW_16 0x40 /* 16 words free */ +#define XMTFW_32 0x80 /* 32 words free */ +#define RCVFW_16 0x00 /* recv fifo watermark = 16 bytes avail */ +#define RCVFW_32 0x10 /* 32 bytes avail */ +#define RCVFW_64 0x20 /* 64 bytes avail */ +#define XMTFWU 0x08 /* xmit fifo watermark update enable */ +#define RCVFWU 0x04 /* recv fifo watermark update enable */ +#define XMTBRST 0x02 /* enable transmit burst mode */ +#define RCVBRST 0x01 /* enable receive burst mode */ + +/* Bits in MACCC */ +#define PROM 0x80 /* promiscuous mode */ +#define DXMT2PD 0x40 /* disable xmit two-part deferral algorithm */ +#define EMBA 0x20 /* enable modified backoff algorithm */ +#define DRCVPA 0x08 /* disable receiving physical address */ +#define DRCVBC 0x04 /* disable receiving broadcasts */ +#define ENXMT 0x02 /* enable transmitter */ +#define ENRCV 0x01 /* enable receiver */ + +/* Bits in PLSCC */ +#define XMTSEL 0x08 /* select DO+/DO- state when idle */ +#define PORTSEL_AUI 0x00 /* select AUI port */ +#define PORTSEL_10T 0x02 /* select 10Base-T port */ +#define PORTSEL_DAI 0x04 /* select DAI port */ +#define PORTSEL_GPSI 0x06 /* select GPSI port */ +#define ENPLSIO 0x01 /* enable optional PLS I/O pins */ + +/* Bits in PHYCC */ +#define LNKFL 0x80 /* reports 10Base-T link failure */ +#define DLNKTST 0x40 /* disable 10Base-T link test */ +#define REVPOL 0x20 /* 10Base-T receiver polarity reversed */ +#define DAPC 0x10 /* disable auto receiver polarity correction */ +#define LRT 0x08 /* low receive threshold for long links */ +#define ASEL 0x04 /* auto-select AUI or 10Base-T port */ +#define RWAKE 0x02 /* remote wake function */ +#define AWAKE 0x01 /* auto wake function */ + +/* Bits in IAC */ +#define ADDRCHG 0x80 /* request address change */ +#define PHYADDR 0x04 /* access physical address */ +#define LOGADDR 0x02 /* access multicast filter */ + +/* Bits in UTR */ +#define RTRE 0x80 /* reserved test register enable. DON'T SET. */ +#define RTRD 0x40 /* reserved test register disable. Sticky */ +#define RPA 0x20 /* accept runt packets */ +#define FCOLL 0x10 /* force collision */ +#define RCVFCSE 0x08 /* receive FCS enable */ +#define LOOP_NONE 0x00 /* no loopback */ +#define LOOP_EXT 0x02 /* external loopback */ +#define LOOP_INT 0x04 /* internal loopback, excludes MENDEC */ +#define LOOP_MENDEC 0x06 /* internal loopback, includes MENDEC */ diff -u --recursive --new-file v2.1.50/linux/drivers/sbus/char/creator.c linux/drivers/sbus/char/creator.c --- v2.1.50/linux/drivers/sbus/char/creator.c Mon Aug 4 16:25:37 1997 +++ linux/drivers/sbus/char/creator.c Sat Aug 16 10:00:28 1997 @@ -1,4 +1,4 @@ -/* $Id: creator.c,v 1.8 1997/07/22 06:14:12 davem Exp $ +/* $Id: creator.c,v 1.7 1997/07/17 02:21:47 davem Exp $ * creator.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/drivers/sbus/char/tcx.c linux/drivers/sbus/char/tcx.c --- v2.1.50/linux/drivers/sbus/char/tcx.c Mon Aug 4 16:25:38 1997 +++ linux/drivers/sbus/char/tcx.c Sat Aug 16 10:00:30 1997 @@ -1,4 +1,4 @@ -/* $Id: tcx.c,v 1.18 1997/07/22 06:14:09 davem Exp $ +/* $Id: tcx.c,v 1.17 1997/07/17 02:21:50 davem Exp $ * tcx.c: SUNW,tcx 24/8bit frame buffer driver * * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/drivers/sbus/char/weitek.c linux/drivers/sbus/char/weitek.c --- v2.1.50/linux/drivers/sbus/char/weitek.c Mon Aug 4 16:25:38 1997 +++ linux/drivers/sbus/char/weitek.c Sat Aug 16 10:00:30 1997 @@ -1,4 +1,4 @@ -/* $Id: weitek.c,v 1.15 1997/07/22 06:14:11 davem Exp $ +/* $Id: weitek.c,v 1.14 1997/07/17 02:21:53 davem Exp $ * weitek.c: Tadpole P9100/P9000 console driver * * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.50/linux/drivers/scsi/Config.in Thu Aug 14 20:49:16 1997 +++ linux/drivers/scsi/Config.in Sat Aug 16 09:53:08 1997 @@ -108,4 +108,9 @@ fi dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI +dep_tristate 'MESH (Power Mac internal SCSI) support' CONFIG_SCSI_MESH $CONFIG_SCSI +if [ "$CONFIG_SCSI_MESH" != "n" ]; then + int ' maximum synchronous transfer rate (MB/s) (0 = async)' CONFIG_SCSI_MESH_SYNC_RATE 5 +fi +dep_tristate '53C94 (Power Mac external SCSI) support' CONFIG_SCSI_MAC53C94 $CONFIG_SCSI endmenu diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.50/linux/drivers/scsi/Makefile Mon Aug 11 14:47:05 1997 +++ linux/drivers/scsi/Makefile Sat Aug 16 09:53:08 1997 @@ -273,6 +273,22 @@ endif endif +ifeq ($(CONFIG_SCSI_MESH),y) +L_OBJS += mesh.o +else + ifeq ($(CONFIG_SCSI_MESH),m) + M_OBJS += mesh.o + endif +endif + +ifeq ($(CONFIG_SCSI_MAC53C94),y) +L_OBJS += mac53c94.o +else + ifeq ($(CONFIG_SCSI_MAC53C94),m) + M_OBJS += mac53c94.o + endif +endif + ifeq ($(CONFIG_SCSI_DEBUG),y) L_OBJS += scsi_debug.o else diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.1.50/linux/drivers/scsi/hosts.c Sat May 24 09:10:24 1997 +++ linux/drivers/scsi/hosts.c Sat Aug 16 09:53:08 1997 @@ -186,6 +186,14 @@ #include "ide-scsi.h" #endif +#ifdef CONFIG_SCSI_MESH +#include "mesh.h" +#endif + +#ifdef CONFIG_SCSI_MAC53C94 +#include "mac53c94.h" +#endif + #ifdef CONFIG_SCSI_DEBUG #include "scsi_debug.h" #endif @@ -338,6 +346,12 @@ #endif #ifdef CONFIG_BLK_DEV_IDESCSI IDESCSI, +#endif +#ifdef CONFIG_SCSI_MESH + SCSI_MESH, +#endif +#ifdef CONFIG_SCSI_MAC53C94 + SCSI_MAC53C94, #endif #ifdef CONFIG_SCSI_DEBUG SCSI_DEBUG, diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c --- v2.1.50/linux/drivers/scsi/mac53c94.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mac53c94.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,502 @@ +/* + * SCSI low-level driver for the 53c94 SCSI bus adaptor found + * on Power Macintosh computers, controlling the external SCSI chain. + * We assume the 53c94 is connected to a DBDMA (descriptor-based DMA) + * controller. + * + * Paul Mackerras, August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "mac53c94.h" + +struct proc_dir_entry proc_scsi_mac53c94 = { + PROC_SCSI_53C94, 5, "53c94", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +enum fsc_phase { + idle, + selecting, + dataing, + completing, + busfreeing, +}; + +struct fsc_state { + volatile struct mac53c94_regs *regs; + int intr; + volatile struct dbdma_regs *dma; + int dmaintr; + int clk_freq; + struct Scsi_Host *host; + struct fsc_state *next; + Scsi_Cmnd *request_q; + Scsi_Cmnd *request_qtail; + Scsi_Cmnd *current_req; /* req we're currently working on */ + enum fsc_phase phase; /* what we're currently trying to do */ + struct dbdma_cmd *dma_cmds; /* space for dbdma commands, aligned */ +}; + +static struct fsc_state *all_53c94s; + +static void mac53c94_init(struct fsc_state *); +static void mac53c94_start(struct fsc_state *); +static void mac53c94_interrupt(int, void *, struct pt_regs *); +static void cmd_done(struct fsc_state *, int result); +static void set_dma_cmds(struct fsc_state *, Scsi_Cmnd *); +static int data_goes_out(Scsi_Cmnd *); + +int +mac53c94_detect(Scsi_Host_Template *tp) +{ + struct device_node *node; + int nfscs; + struct fsc_state *state, **prev_statep; + struct Scsi_Host *host; + void *dma_cmd_space; + unsigned char *clkprop; + int proplen; + + nfscs = 0; + prev_statep = &all_53c94s; + for (node = find_devices("53c94"); node != 0; node = node->next) { + if (node->n_addrs != 2 || node->n_intrs != 2) + panic("53c94: expected 2 addrs and intrs (got %d/%d)", + node->n_addrs, node->n_intrs); + host = scsi_register(tp, sizeof(struct fsc_state)); + if (host == 0) + panic("couldn't register 53c94 host"); + host->unique_id = nfscs; + note_scsi_host(node, host); + + state = (struct fsc_state *) host->hostdata; + if (state == 0) + panic("no 53c94 state"); + state->host = host; + state->regs = (volatile struct mac53c94_regs *) + node->addrs[0].address; + state->intr = node->intrs[0]; + state->dma = (volatile struct dbdma_regs *) + node->addrs[1].address; + state->dmaintr = node->intrs[1]; + + clkprop = get_property(node, "clock-frequency", &proplen); + if (clkprop == NULL || proplen != sizeof(int)) { + printk(KERN_ERR "%s: can't get clock frequency\n", + node->full_name); + state->clk_freq = 25000000; + } else + state->clk_freq = *(int *)clkprop; + + /* Space for dma command list: +1 for stop command, + +1 to allow for aligning. */ + dma_cmd_space = kmalloc((host->sg_tablesize + 2) * + sizeof(struct dbdma_cmd), GFP_KERNEL); + if (dma_cmd_space == 0) + panic("53c94: couldn't allocate dma command space"); + state->dma_cmds = (struct dbdma_cmd *) + DBDMA_ALIGN(dma_cmd_space); + memset(state->dma_cmds, 0, (host->sg_tablesize + 1) + * sizeof(struct dbdma_cmd)); + + *prev_statep = state; + prev_statep = &state->next; + + if (request_irq(state->intr, mac53c94_interrupt, 0, + "53C94", state)) { + printk(KERN_ERR "mac53C94: can't get irq %d\n", state->intr); + } + + mac53c94_init(state); + + ++nfscs; + } + return nfscs; +} + +int +mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +{ + unsigned long flags; + struct fsc_state *state; + +#if 0 + if (data_goes_out(cmd)) { + int i; + printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); + for (i = 0; i < cmd->cmd_len; ++i) + printk(" %.2x", cmd->cmnd[i]); + printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", + cmd->use_sg, cmd->request_bufflen, cmd->request_buffer); + } +#endif + + cmd->scsi_done = done; + cmd->host_scribble = NULL; + + state = (struct fsc_state *) cmd->host->hostdata; + + save_flags(flags); + cli(); + if (state->request_q == NULL) + state->request_q = cmd; + else + state->request_qtail->host_scribble = (void *) cmd; + state->request_qtail = cmd; + + if (state->phase == idle) + mac53c94_start(state); + + restore_flags(flags); + return 0; +} + +int +mac53c94_abort(Scsi_Cmnd *cmd) +{ + return SCSI_ABORT_SNOOZE; +} + +int +mac53c94_reset(Scsi_Cmnd *cmd, unsigned how) +{ + struct fsc_state *state = (struct fsc_state *) cmd->host->hostdata; + volatile struct mac53c94_regs *regs = state->regs; + volatile struct dbdma_regs *dma = state->dma; + unsigned long flags; + + save_flags(flags); + cli(); + st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + regs->command = CMD_SCSI_RESET; /* assert RST */ + eieio(); + udelay(100); /* leave it on for a while (>= 25us) */ + regs->command = CMD_RESET; + eieio(); + udelay(20); + mac53c94_init(state); + regs->command = CMD_NOP; + eieio(); + restore_flags(flags); + return SCSI_RESET_PENDING; +} + +int +mac53c94_command(Scsi_Cmnd *cmd) +{ + printk(KERN_DEBUG "whoops... mac53c94_command called\n"); + return -1; +} + +static void +mac53c94_init(struct fsc_state *state) +{ + volatile struct mac53c94_regs *regs = state->regs; + volatile struct dbdma_regs *dma = state->dma; + int x; + + regs->config1 = state->host->this_id | CF1_PAR_ENABLE; + regs->sel_timeout = TIMO_VAL(250); /* 250ms */ + regs->clk_factor = CLKF_VAL(state->clk_freq); + regs->config2 = CF2_FEATURE_EN; + regs->config3 = 0; + regs->sync_period = 0; + regs->sync_offset = 0; + eieio(); + x = regs->interrupt; + st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); +} + +/* + * Start the next command for a 53C94. + * Should be called with interrupts disabled. + */ +static void +mac53c94_start(struct fsc_state *state) +{ + Scsi_Cmnd *cmd; + volatile struct mac53c94_regs *regs = state->regs; + int i; + + if (state->phase != idle || state->current_req != NULL) + panic("inappropriate mac53c94_start (state=%p)", state); + if (state->request_q == NULL) + return; + state->current_req = cmd = state->request_q; + state->request_q = (Scsi_Cmnd *) cmd->host_scribble; + + /* Off we go */ + regs->count_lo = 0; + regs->count_mid = 0; + regs->count_hi = 0; + eieio(); + regs->command = CMD_NOP + CMD_DMA_MODE; + udelay(1); + eieio(); + regs->command = CMD_FLUSH; + udelay(1); + eieio(); + regs->dest_id = cmd->target; + regs->sync_period = 0; + regs->sync_offset = 0; + eieio(); + + /* load the command into the FIFO */ + for (i = 0; i < cmd->cmd_len; ++i) { + regs->fifo = cmd->cmnd[i]; + eieio(); + } + + /* do select without ATN XXX */ + regs->command = CMD_SELECT; + state->phase = selecting; + + if (cmd->use_sg > 0 || cmd->request_bufflen != 0) + set_dma_cmds(state, cmd); +} + +static void +mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) +{ + struct fsc_state *state = (struct fsc_state *) dev_id; + volatile struct mac53c94_regs *regs = state->regs; + volatile struct dbdma_regs *dma = state->dma; + Scsi_Cmnd *cmd = state->current_req; + int nb, stat, seq, intr; + static int mac53c94_errors; + + /* + * Apparently, reading the interrupt register unlatches + * the status and sequence step registers. + */ + seq = regs->seqstep; + stat = regs->status; + intr = regs->interrupt; + +#if 0 + printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n", + intr, stat, seq, state->phase); +#endif + + if (intr & INTR_RESET) { + /* SCSI bus was reset */ + printk(KERN_INFO "external SCSI bus reset detected\n"); + regs->command = CMD_NOP; + st_le32(&dma->control, RUN << 16); /* stop dma */ + cmd_done(state, DID_RESET << 16); + return; + } + if (intr & INTR_ILL_CMD) { + printk(KERN_ERR "53c94: illegal cmd, intr=%x stat=%x seq=%x phase=%d\n", + intr, stat, seq, state->phase); + cmd_done(state, DID_ERROR << 16); + return; + } + if (stat & STAT_ERROR) { +#if 0 + /* XXX these seem to be harmless? */ + printk("53c94: bad error, intr=%x stat=%x seq=%x phase=%d\n", + intr, stat, seq, state->phase); +#endif + ++mac53c94_errors; + regs->command = CMD_NOP + CMD_DMA_MODE; + eieio(); + } + if (cmd == 0) { + printk(KERN_DEBUG "53c94: interrupt with no command active?\n"); + return; + } + if (stat & STAT_PARITY) { + printk(KERN_ERR "mac53c94: parity error\n"); + cmd_done(state, DID_PARITY << 16); + return; + } + switch (state->phase) { + case selecting: + if (intr & INTR_DISCONNECT) { + /* selection timed out */ + cmd_done(state, DID_BAD_TARGET << 16); + return; + } + if (intr != INTR_BUS_SERV + INTR_DONE) { + printk(KERN_DEBUG "got intr %x during selection\n", intr); + cmd_done(state, DID_ERROR << 16); + return; + } + if ((seq & SS_MASK) != SS_DONE) { + printk(KERN_DEBUG "seq step %x after command\n", seq); + cmd_done(state, DID_ERROR << 16); + return; + } + regs->command = CMD_NOP; + /* set DMA controller going if any data to transfer */ + if ((stat & (STAT_MSG|STAT_CD)) == 0 + && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) { + nb = cmd->SCp.this_residual; + if (nb > 0xfff0) + nb = 0xfff0; + cmd->SCp.this_residual -= nb; + regs->count_lo = nb; + regs->count_mid = nb >> 8; + eieio(); + regs->command = CMD_DMA_MODE + CMD_NOP; + eieio(); + st_le32(&dma->cmdptr, virt_to_phys(state->dma_cmds)); + st_le32(&dma->control, (RUN << 16) | RUN); + eieio(); + regs->command = CMD_DMA_MODE + CMD_XFER_DATA; + state->phase = dataing; + break; + } else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) { + /* up to status phase already */ + regs->command = CMD_I_COMPLETE; + state->phase = completing; + } else { + printk(KERN_DEBUG "in unexpected phase %x after cmd\n", + stat & STAT_PHASE); + cmd_done(state, DID_ERROR << 16); + return; + } + break; + + case dataing: + if (intr != INTR_BUS_SERV) { + printk(KERN_DEBUG "got intr %x before status\n", intr); + cmd_done(state, DID_ERROR << 16); + return; + } + if (cmd->SCp.this_residual != 0 + && (stat & (STAT_MSG|STAT_CD)) == 0) { + /* Set up the count regs to transfer more */ + nb = cmd->SCp.this_residual; + if (nb > 0xfff0) + nb = 0xfff0; + cmd->SCp.this_residual -= nb; + regs->count_lo = nb; + regs->count_mid = nb >> 8; + eieio(); + regs->command = CMD_DMA_MODE + CMD_NOP; + eieio(); + regs->command = CMD_DMA_MODE + CMD_XFER_DATA; + break; + } + if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) { + printk(KERN_DEBUG "intr %x before data xfer complete\n", intr); + } + st_le32(&dma->control, RUN << 16); /* stop dma */ + /* should check dma status */ + regs->command = CMD_I_COMPLETE; + state->phase = completing; + break; + case completing: + if (intr != INTR_DONE) { + printk(KERN_DEBUG "got intr %x on completion\n", intr); + cmd_done(state, DID_ERROR << 16); + return; + } + cmd->SCp.Status = regs->fifo; eieio(); + cmd->SCp.Message = regs->fifo; eieio(); + cmd->result = + regs->command = CMD_ACCEPT_MSG; + state->phase = busfreeing; + break; + case busfreeing: + if (intr != INTR_DISCONNECT) { + printk(KERN_DEBUG "got intr %x when expected disconnect\n", intr); + } + cmd_done(state, (DID_OK << 16) + (cmd->SCp.Message << 8) + + cmd->SCp.Status); + break; + default: + printk(KERN_DEBUG "don't know about phase %d\n", state->phase); + } +} + +static void +cmd_done(struct fsc_state *state, int result) +{ + Scsi_Cmnd *cmd; + + cmd = state->current_req; + if (cmd != 0) { + cmd->result = result; + (*cmd->scsi_done)(cmd); + state->current_req = NULL; + } + state->phase = idle; + mac53c94_start(state); +} + +/* + * Set up DMA commands for transferring data. + */ +static void +set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd) +{ + int i, dma_cmd, total; + struct scatterlist *scl; + struct dbdma_cmd *dcmds; + + dma_cmd = data_goes_out(cmd)? OUTPUT_MORE: INPUT_MORE; + dcmds = state->dma_cmds; + if (cmd->use_sg > 0) { + total = 0; + scl = (struct scatterlist *) cmd->buffer; + for (i = 0; i < cmd->use_sg; ++i) { + if (scl->length > 0xffff) + panic("mac53c94: scatterlist element >= 64k"); + total += scl->length; + st_le16(&dcmds->req_count, scl->length); + st_le16(&dcmds->command, dma_cmd); + st_le32(&dcmds->phy_addr, virt_to_phys(scl->address)); + dcmds->xfer_status = 0; + ++scl; + ++dcmds; + } + } else { + total = cmd->request_bufflen; + if (total > 0xffff) + panic("mac53c94: transfer size >= 64k"); + st_le16(&dcmds->req_count, total); + st_le32(&dcmds->phy_addr, virt_to_phys(cmd->request_buffer)); + dcmds->xfer_status = 0; + ++dcmds; + } + dma_cmd += OUTPUT_LAST - OUTPUT_MORE; + st_le16(&dcmds[-1].command, dma_cmd); + st_le16(&dcmds->command, DBDMA_STOP); + cmd->SCp.this_residual = total; +} + +/* + * Work out whether data will be going out from the host adaptor or into it. + * (If this information is available from somewhere else in the scsi + * code, somebody please let me know :-) + */ +static int +data_goes_out(Scsi_Cmnd *cmd) +{ + switch (cmd->cmnd[0]) { + case WRITE_6: + case WRITE_10: + case WRITE_12: /* any others? */ + return 1; + default: + return 0; + } +} diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mac53c94.h linux/drivers/scsi/mac53c94.h --- v2.1.50/linux/drivers/scsi/mac53c94.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mac53c94.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,246 @@ +/* + * mac53c94.h: definitions for the driver for the 53c94 SCSI bus adaptor + * found on Power Macintosh computers, controlling the external SCSI chain. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#ifndef _MAC53C94_H +#define _MAC53C94_H + +extern struct proc_dir_entry proc_scsi_mac53c94; + +int mac53c94_detect(Scsi_Host_Template *); +int mac53c94_command(Scsi_Cmnd *); +int mac53c94_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int mac53c94_abort(Scsi_Cmnd *); +int mac53c94_reset(Scsi_Cmnd *, unsigned int); + +#define SCSI_MAC53C94 { \ + NULL, /* next */ \ + NULL, /* usage_count */ \ + &proc_scsi_mac53c94, /* proc_dir */ \ + NULL, /* proc_info */ \ + "53C94", /* name */ \ + mac53c94_detect, /* detect */ \ + NULL, /* release */ \ + NULL, /* info */ \ + mac53c94_command, /* command */ \ + mac53c94_queue, /* queuecommand */ \ + mac53c94_abort, /* abort */ \ + mac53c94_reset, /* reset */ \ + NULL, /* slave_attach */ \ + NULL, /* bios_param */ \ + 1, /* can_queue */ \ + 7, /* this_id */ \ + SG_ALL, /* sg_tablesize */ \ + 1, /* cmd_per_lun */ \ + 0, /* present */ \ + 0, /* unchecked_isa_dma */ \ + DISABLE_CLUSTERING, /* use_clustering */ \ +} + +/* + * Registers in the 53C94 controller. + */ + +struct mac53c94_regs { + unsigned char count_lo; + char pad0[15]; + unsigned char count_mid; + char pad1[15]; + unsigned char fifo; + char pad2[15]; + unsigned char command; + char pad3[15]; + unsigned char status; + char pad4[15]; + unsigned char interrupt; + char pad5[15]; + unsigned char seqstep; + char pad6[15]; + unsigned char flags; + char pad7[15]; + unsigned char config1; + char pad8[15]; + unsigned char clk_factor; + char pad9[15]; + unsigned char test; + char pad10[15]; + unsigned char config2; + char pad11[15]; + unsigned char config3; + char pad12[15]; + unsigned char config4; + char pad13[15]; + unsigned char count_hi; + char pad14[15]; + unsigned char fifo_res; + char pad15[15]; +}; + +/* + * Alternate functions for some registers. + */ +#define dest_id status +#define sel_timeout interrupt +#define sync_period seqstep +#define sync_offset flags + +/* + * Bits in command register. + */ +#define CMD_DMA_MODE 0x80 +#define CMD_MODE_MASK 0x70 +#define CMD_MODE_INIT 0x10 +#define CMD_MODE_TARG 0x20 +#define CMD_MODE_DISC 0x40 + +#define CMD_NOP 0 +#define CMD_FLUSH 1 +#define CMD_RESET 2 +#define CMD_SCSI_RESET 3 + +#define CMD_XFER_DATA 0x10 +#define CMD_I_COMPLETE 0x11 +#define CMD_ACCEPT_MSG 0x12 +#define CMD_XFER_PAD 0x18 +#define CMD_SET_ATN 0x1a +#define CMD_CLR_ATN 0x1b + +#define CMD_SEND_MSG 0x20 +#define CMD_SEND_STATUS 0x21 +#define CMD_SEND_DATA 0x22 +#define CMD_DISC_SEQ 0x23 +#define CMD_TERMINATE 0x24 +#define CMD_T_COMPLETE 0x25 +#define CMD_DISCONNECT 0x27 +#define CMD_RECV_MSG 0x28 +#define CMD_RECV_CDB 0x29 +#define CMD_RECV_DATA 0x2a +#define CMD_RECV_CMD 0x2b +#define CMD_ABORT_DMA 0x04 + +#define CMD_RESELECT 0x40 +#define CMD_SELECT 0x41 +#define CMD_SELECT_ATN 0x42 +#define CMD_SELATN_STOP 0x43 +#define CMD_ENABLE_SEL 0x44 +#define CMD_DISABLE_SEL 0x45 +#define CMD_SEL_ATN3 0x46 +#define CMD_RESEL_ATN3 0x47 + +/* + * Bits in status register. + */ +#define STAT_IRQ 0x80 +#define STAT_ERROR 0x40 +#define STAT_PARITY 0x20 +#define STAT_TC_ZERO 0x10 +#define STAT_DONE 0x08 +#define STAT_PHASE 0x07 +#define STAT_MSG 0x04 +#define STAT_CD 0x02 +#define STAT_IO 0x01 + +/* + * Bits in interrupt register. + */ +#define INTR_RESET 0x80 /* SCSI bus was reset */ +#define INTR_ILL_CMD 0x40 /* illegal command */ +#define INTR_DISCONNECT 0x20 /* we got disconnected */ +#define INTR_BUS_SERV 0x10 /* bus service requested */ +#define INTR_DONE 0x08 /* function completed */ +#define INTR_RESELECTED 0x04 /* we were reselected */ +#define INTR_SEL_ATN 0x02 /* we were selected, ATN asserted */ +#define INTR_SELECT 0x01 /* we were selected, ATN negated */ + +/* + * Encoding for the select timeout. + */ +#define TIMO_VAL(x) ((x) * 5000 / 7682) + +/* + * Bits in sequence step register. + */ +#define SS_MASK 7 +#define SS_ARB_SEL 0 /* Selection & arbitration complete */ +#define SS_MSG_SENT 1 /* One message byte sent */ +#define SS_NOT_CMD 2 /* Not in command phase */ +#define SS_PHASE_CHG 3 /* Early phase change, cmd bytes lost */ +#define SS_DONE 4 /* Command was sent OK */ + +/* + * Encoding for sync transfer period. + */ +#define SYNCP_MASK 0x1f +#define SYNCP_MIN 4 +#define SYNCP_MAX 31 + +/* + * Bits in flags register. + */ +#define FLAGS_FIFO_LEV 0x1f +#define FLAGS_SEQ_STEP 0xe0 + +/* + * Encoding for sync offset. + */ +#define SYNCO_MASK 0x0f +#define SYNCO_ASS_CTRL 0x30 /* REQ/ACK assertion control */ +#define SYNCO_NEG_CTRL 0xc0 /* REQ/ACK negation control */ + +/* + * Bits in config1 register. + */ +#define CF1_SLOW_CABLE 0x80 /* Slow cable mode */ +#define CF1_NO_RES_REP 0x40 /* Disable SCSI reset reports */ +#define CF1_PAR_TEST 0x20 /* Parity test mode enable */ +#define CF1_PAR_ENABLE 0x10 /* Enable parity checks */ +#define CF1_TEST 0x08 /* Chip tests */ +#define CF1_MY_ID 0x07 /* Controller's address on bus */ + +/* + * Encoding for clk_factor register. + */ +#define CLKF_MASK 7 +#define CLKF_VAL(freq) ((((freq) + 4999999) / 5000000) & CLKF_MASK) + +/* + * Bits in test mode register. + */ +#define TEST_TARGET 1 /* target test mode */ +#define TEST_INITIATOR 2 /* initiator test mode */ +#define TEST_TRISTATE 4 /* tristate (hi-z) test mode */ + +/* + * Bits in config2 register. + */ +#define CF2_RFB 0x80 +#define CF2_FEATURE_EN 0x40 /* enable features / phase latch */ +#define CF2_BYTECTRL 0x20 +#define CF2_DREQ_HIZ 0x10 +#define CF2_SCSI2 0x08 +#define CF2_PAR_ABORT 0x04 /* bad parity target abort */ +#define CF2_REG_PARERR 0x02 /* register parity error */ +#define CF2_DMA_PARERR 0x01 /* DMA parity error */ + +/* + * Bits in the config3 register. + */ +#define CF3_ID_MSG_CHK 0x80 +#define CF3_3B_MSGS 0x40 +#define CF3_CDB10 0x20 +#define CF3_FASTSCSI 0x10 /* enable fast SCSI support */ +#define CF3_FASTCLOCK 0x08 +#define CF3_SAVERESID 0x04 +#define CF3_ALT_DMA 0x02 +#define CF3_THRESH_8 0x01 + +/* + * Bits in the config4 register. + */ +#define CF4_EAN 0x04 +#define CF4_TEST 0x02 +#define CF4_BBTE 0x01 + +#endif /* _MAC53C94_H */ diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c --- v2.1.50/linux/drivers/scsi/mesh.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mesh.c Sat Aug 16 10:09:10 1997 @@ -0,0 +1,1321 @@ +/* + * SCSI low-level driver for the MESH (Macintosh Enhanced SCSI Hardware) + * bus adaptor found on Power Macintosh computers. + * We assume the MESH is connected to a DBDMA (descriptor-based DMA) + * controller. + * + * Paul Mackerras, August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "mesh.h" + +#if 0 +#undef KERN_DEBUG +#define KERN_DEBUG KERN_WARNING +#endif + +#if CONFIG_SCSI_MESH_SYNC_RATE == 0 +int mesh_sync_period = 100; +int mesh_sync_offset = 0; +#else +int mesh_sync_period = 1000 / CONFIG_SCSI_MESH_SYNC_RATE; /* ns */ +int mesh_sync_offset = 15; +#endif + +int mesh_sync_targets = 0xff; /* targets to set synchronous (bitmap) */ +int mesh_resel_targets = 0xff; /* targets that we let disconnect (bitmap) */ +int mesh_debug_targets = 0; /* print debug for these targets */ + +#define ALLOW_SYNC(tgt) ((mesh_sync_targets >> (tgt)) & 1) +#define ALLOW_RESEL(tgt) ((mesh_resel_targets >> (tgt)) & 1) +#define ALLOW_DEBUG(tgt) ((mesh_debug_targets >> (tgt)) & 1) +#define DEBUG_TARGET(cmd) ((cmd) && ALLOW_DEBUG((cmd)->target)) + +struct proc_dir_entry proc_scsi_mesh = { + PROC_SCSI_MESH, 4, "mesh", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +enum mesh_phase { + idle, + arbitrating, + selecting, + commanding, + dataing, + statusing, + busfreeing, + disconnecting, + reselecting +}; + +enum msg_phase { + msg_none, + msg_out, + msg_out_xxx, + msg_out_last, + msg_in, +}; + +enum sdtr_phase { + do_sdtr, + sdtr_sent, + sdtr_done +}; + +struct mesh_target { + enum sdtr_phase sdtr_state; + enum mesh_phase phase; + int sync_params; + int data_goes_out; + Scsi_Cmnd *current_req; + u32 saved_ptr; +}; + +struct mesh_state { + volatile struct mesh_regs *mesh; + int meshintr; + volatile struct dbdma_regs *dma; + int dmaintr; + struct Scsi_Host *host; + struct mesh_state *next; + Scsi_Cmnd *request_q; + Scsi_Cmnd *request_qtail; + enum mesh_phase phase; /* what we're currently trying to do */ + enum msg_phase msgphase; + int conn_tgt; /* target we're connected to */ + Scsi_Cmnd *current_req; /* req we're currently working on */ + int data_ptr; + int data_goes_out; /* guess as to data direction */ + int dma_started; + int dma_count; + int expect_reply; + int n_msgin; + u8 msgin[16]; + int n_msgout; + int last_n_msgout; + u8 msgout[16]; + struct dbdma_cmd *dma_cmds; /* space for dbdma commands, aligned */ + int clk_freq; + struct mesh_target tgts[8]; + struct tq_struct tqueue; + Scsi_Cmnd *completed_q; + Scsi_Cmnd *completed_qtail; +}; + +static struct mesh_state *all_meshes; + +static void mesh_init(struct mesh_state *); +static int mesh_notify_reboot(struct notifier_block *, unsigned long, void *); +static void mesh_dump_regs(struct mesh_state *); +static void mesh_start(struct mesh_state *); +static void finish_cmds(void *); +static void add_sdtr_msg(struct mesh_state *); +static void set_sdtr(struct mesh_state *, int, int); +static void start_phase(struct mesh_state *); +static void get_msgin(struct mesh_state *); +static int msgin_length(struct mesh_state *); +static void cmd_complete(struct mesh_state *); +static void phase_mismatch(struct mesh_state *); +static void reselected(struct mesh_state *); +static void handle_reset(struct mesh_state *); +static void mesh_interrupt(int, void *, struct pt_regs *); +static void handle_msgin(struct mesh_state *); +static void mesh_done(struct mesh_state *); +static void mesh_completed(struct mesh_state *, Scsi_Cmnd *); +static void set_dma_cmds(struct mesh_state *, Scsi_Cmnd *); +static void halt_dma(struct mesh_state *); +static int data_goes_out(Scsi_Cmnd *); + +static struct notifier_block mesh_notifier = { + mesh_notify_reboot, + NULL, + 0 +}; + +int +mesh_detect(Scsi_Host_Template *tp) +{ + struct device_node *mesh; + int nmeshes, tgt, *cfp, minper; + struct mesh_state *ms, **prev_statep; + struct Scsi_Host *mesh_host; + void *dma_cmd_space; + + nmeshes = 0; + prev_statep = &all_meshes; + for (mesh = find_devices("mesh"); mesh != 0; mesh = mesh->next) { + if (mesh->n_addrs != 2 || mesh->n_intrs != 2) + panic("mesh: expected 2 addrs and intrs (got %d/%d)", + mesh->n_addrs, mesh->n_intrs); + mesh_host = scsi_register(tp, sizeof(struct mesh_state)); + if (mesh_host == 0) + panic("couldn't register mesh host"); + mesh_host->unique_id = nmeshes; + note_scsi_host(mesh, mesh_host); + + ms = (struct mesh_state *) mesh_host->hostdata; + if (ms == 0) + panic("no mesh state"); + memset(ms, 0, sizeof(*ms)); + ms->host = mesh_host; + ms->mesh = (volatile struct mesh_regs *) + mesh->addrs[0].address; + ms->meshintr = mesh->intrs[0]; + ms->dma = (volatile struct dbdma_regs *) + mesh->addrs[1].address; + ms->dmaintr = mesh->intrs[1]; + + /* Space for dma command list: +1 for stop command, + +1 to allow for aligning. */ + dma_cmd_space = kmalloc((mesh_host->sg_tablesize + 2) * + sizeof(struct dbdma_cmd), GFP_KERNEL); + if (dma_cmd_space == 0) + panic("mesh: couldn't allocate dma command space"); + ms->dma_cmds = (struct dbdma_cmd *) DBDMA_ALIGN(dma_cmd_space); + memset(ms->dma_cmds, 0, (mesh_host->sg_tablesize + 1) + * sizeof(struct dbdma_cmd)); + + ms->current_req = 0; + for (tgt = 0; tgt < 8; ++tgt) { + ms->tgts[tgt].sdtr_state = do_sdtr; + ms->tgts[tgt].sync_params = ASYNC_PARAMS; + ms->tgts[tgt].current_req = 0; + } + + ms->tqueue.routine = finish_cmds; + ms->tqueue.data = ms; + + *prev_statep = ms; + prev_statep = &ms->next; + + if (request_irq(ms->meshintr, mesh_interrupt, 0, "MESH", ms)) { + printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr); + } + + cfp = (int *) get_property(mesh, "clock-frequency", NULL); + if (cfp) { + ms->clk_freq = *cfp; + } else { + printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n"); + ms->clk_freq = 50000000; + } + /* The maximum sync rate is clock / 5; increase + mesh_sync_period if necessary. */ + minper = 1000000000 / (ms->clk_freq / 5); /* ns */ + if (mesh_sync_period < minper) + mesh_sync_period = minper; + + mesh_init(ms); + + ++nmeshes; + } + if (nmeshes > 0) + register_reboot_notifier(&mesh_notifier); + + return nmeshes; +} + +int +mesh_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +{ + unsigned long flags; + struct mesh_state *ms; + +#if 0 + if (data_goes_out(cmd)) { + printk(KERN_DEBUG "mesh_queue %p: command is", cmd); + for (i = 0; i < cmd->cmd_len; ++i) + printk(" %.2x", cmd->cmnd[i]); + printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n", + cmd->use_sg, cmd->request_bufflen, cmd->request_buffer); + } +#endif + + cmd->scsi_done = done; + cmd->host_scribble = NULL; + + ms = (struct mesh_state *) cmd->host->hostdata; + + save_flags(flags); + cli(); + if (ms->request_q == NULL) + ms->request_q = cmd; + else + ms->request_qtail->host_scribble = (void *) cmd; + ms->request_qtail = cmd; + + if (ms->phase == idle) + mesh_start(ms); + + restore_flags(flags); + return 0; +} + +int +mesh_abort(Scsi_Cmnd *cmd) +{ + printk(KERN_DEBUG "mesh_abort(%p)\n", cmd); + mesh_dump_regs((struct mesh_state *)(cmd->host->hostdata)); + return SCSI_ABORT_SNOOZE; +} + +static void +mesh_dump_regs(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + int t; + struct mesh_target *tp; + + printk(KERN_DEBUG "mesh: state at %p, regs at %p, dma at %p\n", + ms, mr, md); + printk(KERN_DEBUG " ct=%4x seq=%2x bs=%4x fc=%2x exc=%2x err=%2x sp=%2x\n", + (mr->count_hi << 8) + mr->count_lo, mr->sequence, + (mr->bus_status1 << 8) + mr->bus_status0, mr->fifo_count, + mr->exception, mr->error, mr->sync_params); + printk(KERN_DEBUG " dma stat=%x cmdptr=%x\n", + in_le32(&md->status), in_le32(&md->cmdptr)); + printk(KERN_DEBUG " phase=%d msgphase=%d conn_tgt=%d data_ptr=%d\n", + ms->phase, ms->msgphase, ms->conn_tgt, ms->data_ptr); + printk(KERN_DEBUG " goes_out=%d dma_st=%d dma_ct=%d n_msgout=%d\n", + ms->data_goes_out, ms->dma_started, ms->dma_count, ms->n_msgout); + for (t = 0; t < 8; ++t) { + tp = &ms->tgts[t]; + if (tp->current_req == NULL) + continue; + printk(KERN_DEBUG " target %d: req=%p phase=%d saved_ptr=%d\n", + t, tp->current_req, tp->phase, tp->saved_ptr); + } +} + +int +mesh_reset(Scsi_Cmnd *cmd, unsigned how) +{ + struct mesh_state *ms = (struct mesh_state *) cmd->host->hostdata; + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + unsigned long flags; + int ret; + + printk(KERN_DEBUG "mesh_reset %x\n", how); + ret = SCSI_RESET_BUS_RESET; + save_flags(flags); + cli(); + out_8(&mr->exception, 0xff); /* clear all exception bits */ + out_8(&mr->error, 0xff); /* clear all error bits */ + out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + if (how & SCSI_RESET_SUGGEST_HOST_RESET) { + out_8(&mr->sequence, SEQ_RESETMESH); + ret |= SCSI_RESET_HOST_RESET; + udelay(1); + out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + } + out_8(&mr->bus_status1, BS1_RST); /* assert RST */ + udelay(30); /* leave it on for >= 25us */ + out_8(&mr->bus_status1, 0); /* negate RST */ +#ifdef DO_ASYNC_RESET + if (how & SCSI_RESET_ASYNCHRONOUS) { + restore_flags(flags); + ret |= SCSI_RESET_PENDING; + } else +#endif + { + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + handle_reset(ms); + restore_flags(flags); + finish_cmds(ms); + ret |= SCSI_RESET_SUCCESS; + } + return ret; +} + +/* + * If we leave drives set for synchronous transfers (especially + * CDROMs), and reboot to MacOS, it gets confused, poor thing. + * So, on reboot we reset the SCSI bus. + */ +static int +mesh_notify_reboot(struct notifier_block *this, unsigned long code, void *x) +{ + struct mesh_state *ms; + volatile struct mesh_regs *mr; + + if (code == SYS_DOWN || code == SYS_HALT) { + printk(KERN_INFO "resetting MESH scsi bus(es)\n"); + for (ms = all_meshes; ms != 0; ms = ms->next) { + mr = ms->mesh; + out_8(&mr->intr_mask, 0); + out_8(&mr->interrupt, + INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->bus_status1, BS1_RST); + udelay(30); + out_8(&mr->bus_status1, 0); + } + } + return NOTIFY_DONE; +} + +int +mesh_command(Scsi_Cmnd *cmd) +{ + printk(KERN_WARNING "whoops... mesh_command called\n"); + return -1; +} + +static void +mesh_init(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + + out_8(&mr->interrupt, 0xff); /* clear all interrupt bits */ + out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + out_8(&mr->source_id, ms->host->this_id); + out_8(&mr->sel_timeout, 25); /* 250ms */ + out_8(&mr->sync_params, ASYNC_PARAMS); /* asynchronous initially */ + out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); +} + +/* + * Start the next command for a MESH. + * Should be called with interrupts disabled. + */ +static void +mesh_start(struct mesh_state *ms) +{ + Scsi_Cmnd *cmd, *prev, *next; + volatile struct mesh_regs *mr = ms->mesh; + + if (ms->phase != idle || ms->current_req != NULL) + panic("inappropriate mesh_start (ms=%p)", ms); + + prev = NULL; + for (cmd = ms->request_q; ; cmd = (Scsi_Cmnd *) cmd->host_scribble) { + if (cmd == NULL) + return; + if (ms->tgts[cmd->target].current_req == NULL) + break; + prev = cmd; + } + next = (Scsi_Cmnd *) cmd->host_scribble; + if (prev == NULL) + ms->request_q = next; + else + prev->host_scribble = (void *) next; + if (next == NULL) + ms->request_qtail = prev; + + ms->current_req = cmd; + ms->data_goes_out = data_goes_out(cmd); + ms->tgts[cmd->target].current_req = cmd; + +#if 1 + if (DEBUG_TARGET(cmd)) { + int i; + printk(KERN_DEBUG "mesh_start: %p ser=%lu tgt=%d cmd=", + cmd, cmd->serial_number, cmd->target); + for (i = 0; i < cmd->cmd_len; ++i) + printk(" %x", cmd->cmnd[i]); + printk(" use_sg=%d buffer=%p bufflen=%u\n", + cmd->use_sg, cmd->request_buffer, cmd->request_bufflen); + } +#endif + + /* Off we go */ + out_8(&mr->sequence, SEQ_ARBITRATE); + + ms->phase = arbitrating; + ms->msgphase = msg_none; + ms->data_ptr = 0; + ms->dma_started = 0; + ms->n_msgout = 0; + ms->last_n_msgout = 0; + ms->expect_reply = 0; + ms->conn_tgt = cmd->target; + ms->tgts[cmd->target].saved_ptr = 0; +} + +static void +finish_cmds(void *data) +{ + struct mesh_state *ms = data; + Scsi_Cmnd *cmd; + unsigned long flags; + + for (;;) { + save_flags(flags); + cli(); + cmd = ms->completed_q; + if (cmd == NULL) { + restore_flags(flags); + break; + } + ms->completed_q = (Scsi_Cmnd *) cmd->host_scribble; + restore_flags(flags); + (*cmd->scsi_done)(cmd); + } +} + +static inline void +add_sdtr_msg(struct mesh_state *ms) +{ + int i = ms->n_msgout; + + ms->msgout[i] = EXTENDED_MESSAGE; + ms->msgout[i+1] = 3; + ms->msgout[i+2] = EXTENDED_SDTR; + ms->msgout[i+3] = mesh_sync_period/4; + ms->msgout[i+4] = (ALLOW_SYNC(ms->conn_tgt)? mesh_sync_offset: 0); + ms->n_msgout = i + 5; +} + +static void +set_sdtr(struct mesh_state *ms, int period, int offset) +{ + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + volatile struct mesh_regs *mr = ms->mesh; + int v, tr; + + tp->sdtr_state = sdtr_done; + if (offset == 0) { + /* asynchronous */ + if (SYNC_OFF(tp->sync_params)) + printk(KERN_INFO "mesh: target %d now asynchronous\n", + ms->conn_tgt); + tp->sync_params = ASYNC_PARAMS; + out_8(&mr->sync_params, ASYNC_PARAMS); + return; + } + /* + * We need to compute ceil(clk_freq * period / 500e6) - 2 + * without incurring overflow. + */ + v = (ms->clk_freq / 5000) * period; + if (v <= 250000) { + /* special case: sync_period == 5 * clk_period */ + v = 0; + /* units of tr are 100kB/s */ + tr = (ms->clk_freq + 250000) / 500000; + } else { + /* sync_period == (v + 2) * 2 * clk_period */ + v = (v + 99999) / 100000 - 2; + if (v > 15) + v = 15; /* oops */ + tr = ((ms->clk_freq / (v + 2)) + 199999) / 200000; + } + if (offset > 15) + offset = 15; /* can't happen */ + tp->sync_params = SYNC_PARAMS(offset, v); + out_8(&mr->sync_params, tp->sync_params); + printk(KERN_INFO "mesh: target %d synchronous at %d.%d MB/s\n", + ms->conn_tgt, tr/10, tr%10); +} + +static void +start_phase(struct mesh_state *ms) +{ + int i, seq, nb; + volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs *md = ms->dma; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + + if (cmd == 0) { + printk(KERN_ERR "mesh: start_phase but no cmd?\n"); + return; + } + seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0); + switch (ms->msgphase) { + case msg_none: + break; + + case msg_in: + out_8(&mr->count_hi, 0); + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGIN + seq); + ms->n_msgin = 0; + return; + + case msg_out: + /* + * To make sure ATN drops before we assert ACK for + * the last byte of the message, we have to do the + * last byte specially. + */ + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "mesh: sending %d msg bytes:", + ms->n_msgout); + for (i = 0; i < ms->n_msgout; ++i) + printk(" %x", ms->msgout[i]); + printk("\n"); + } + out_8(&mr->count_hi, 0); + if (ms->n_msgout == 1) { + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + udelay(1); + out_8(&mr->fifo, ms->msgout[0]); + ms->msgphase = msg_out_last; + } else { + out_8(&mr->count_lo, ms->n_msgout - 1); + out_8(&mr->sequence, SEQ_MSGOUT + seq); + for (i = 0; i < ms->n_msgout - 1; ++i) + out_8(&mr->fifo, ms->msgout[i]); + } + return; + + default: + printk(KERN_ERR "mesh bug: start_phase msgphase=%d\n", + ms->msgphase); + } + + switch (ms->phase) { + case selecting: + out_8(&mr->dest_id, cmd->target); + out_8(&mr->sequence, SEQ_SELECT + SEQ_ATN); + break; + case commanding: + out_8(&mr->sync_params, tp->sync_params); + out_8(&mr->count_hi, 0); + out_8(&mr->count_lo, cmd->cmd_len); + out_8(&mr->sequence, SEQ_COMMAND + seq); + for (i = 0; i < cmd->cmd_len; ++i) + out_8(&mr->fifo, cmd->cmnd[i]); + break; + case dataing: + /* transfer data, if any */ + if (!ms->dma_started) { + set_dma_cmds(ms, cmd); + out_le32(&md->cmdptr, virt_to_phys(ms->dma_cmds)); + out_le32(&md->control, (RUN << 16) | RUN); + ms->dma_started = 1; + } + nb = ms->dma_count; + if (nb > 0xfff0) + nb = 0xfff0; + ms->dma_count -= nb; + ms->data_ptr += nb; + out_8(&mr->count_lo, nb); + out_8(&mr->count_hi, nb >> 8); + out_8(&mr->sequence, (ms->data_goes_out? + SEQ_DATAOUT: SEQ_DATAIN) + SEQ_DMA_MODE + seq); + break; + case statusing: + out_8(&mr->count_hi, 0); + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_STATUS + seq); + break; + case busfreeing: + case disconnecting: + out_8(&mr->sequence, SEQ_ENBRESEL); + udelay(1); + out_8(&mr->sequence, SEQ_BUSFREE); + break; + default: + printk(KERN_ERR "mesh: start_phase called with phase=%d\n", + ms->phase); + } + +} + +static inline void +get_msgin(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + int i, n; + + n = mr->fifo_count; + if (n != 0) { + i = ms->n_msgin; + ms->n_msgin = i + n; + for (; n > 0; --n) + ms->msgin[i++] = in_8(&mr->fifo); + } +} + +static inline int +msgin_length(struct mesh_state *ms) +{ + int b, n; + + n = 1; + if (ms->n_msgin > 0) { + b = ms->msgin[0]; + if (b == 1) { + /* extended message */ + n = ms->n_msgin < 2? 2: ms->msgin[1] + 2; + } else if (0x20 <= b && b <= 0x2f) { + /* 2-byte message */ + n = 2; + } + } + return n; +} + +static void +cmd_complete(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + int seq, n, t; + + seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0); + switch (ms->msgphase) { + case msg_out_xxx: + /* huh? we expected a phase mismatch */ + ms->n_msgin = 0; + ms->msgphase = msg_in; + /* fall through */ + + case msg_in: + /* should have some message bytes in fifo */ + get_msgin(ms); + n = msgin_length(ms); + if (ms->n_msgin < n) { + out_8(&mr->count_lo, n - ms->n_msgin); + out_8(&mr->sequence, SEQ_MSGIN + seq); + } else { + ms->msgphase = msg_none; + handle_msgin(ms); + start_phase(ms); + } + break; + + case msg_out: + /* + * To get the right timing on ATN wrt ACK, we have + * to get the MESH to drop ACK, wait until REQ gets + * asserted, then drop ATN. To do this we first + * issue a SEQ_MSGOUT with ATN and wait for REQ, + * then change the command to a SEQ_MSGOUT w/o ATN. + * If we don't see REQ in a reasonable time, we + * change the command to SEQ_MSGIN with ATN, + * wait for the phase mismatch interrupt, then + * issue the SEQ_MSGOUT without ATN. + */ + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG + SEQ_ATN); + t = 30; /* wait up to 30us */ + while ((mr->bus_status0 & BS0_REQ) == 0 && --t >= 0) + udelay(1); + if (mr->bus_status0 & BS0_REQ) { + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + udelay(1); + out_8(&mr->fifo, ms->msgout[ms->n_msgout-1]); + ms->msgphase = msg_out_last; + } else { + out_8(&mr->sequence, SEQ_MSGIN + SEQ_ACTIVE_NEG + SEQ_ATN); + ms->msgphase = msg_out_xxx; + } + break; + + case msg_out_last: + ms->last_n_msgout = ms->n_msgout; + ms->n_msgout = 0; + ms->msgphase = ms->expect_reply? msg_in: msg_none; + start_phase(ms); + break; + + case msg_none: + switch (ms->phase) { + case selecting: + ms->msgout[0] = IDENTIFY(ALLOW_RESEL(cmd->target), cmd->lun); + ms->n_msgout = 1; + ms->expect_reply = 0; + if (tp->sdtr_state == do_sdtr) { + /* add SDTR message */ + add_sdtr_msg(ms); + ms->expect_reply = 1; + tp->sdtr_state = sdtr_sent; + } + ms->msgphase = msg_out; + /* + * We need to wait for REQ before dropping ATN. + * We wait for at most 30us, then fall back to + * a scheme where we issue a SEQ_COMMAND with ATN, + * which will give us a phase mismatch interrupt + * when REQ does come, and then we send the message. + */ + t = 30; /* wait up to 30us */ + while ((mr->bus_status0 & BS0_REQ) == 0) { + if (--t < 0) { + ms->msgphase = msg_none; + break; + } + udelay(1); + } + break; + case dataing: + if (ms->dma_count != 0) { + start_phase(ms); + return; + } + halt_dma(ms); + break; + case statusing: + cmd->SCp.Status = mr->fifo; + cmd->result = (DID_OK << 16) + cmd->SCp.Status; + ms->msgphase = msg_in; + if (DEBUG_TARGET(cmd)) + printk(KERN_DEBUG "mesh: status is %x\n", + cmd->SCp.Status); + break; + case busfreeing: + mesh_done(ms); + return; + case disconnecting: + ms->current_req = 0; + ms->phase = idle; + mesh_start(ms); + return; + default: + break; + } + ++ms->phase; + start_phase(ms); + break; + } +} + +static void phase_mismatch(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + int phase; + + phase = mr->bus_status0 & BS0_PHASE; + if (ms->msgphase == msg_out_xxx && phase == BP_MSGOUT) { + /* output the last byte of the message, without ATN */ + out_8(&mr->count_lo, 1); + out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG); + udelay(1); + out_8(&mr->fifo, ms->msgout[ms->n_msgout-1]); + ms->msgphase = msg_out_last; + return; + } + + if (ms->msgphase == msg_in) { + get_msgin(ms); + if (ms->n_msgin) + handle_msgin(ms); + } + + if (ms->dma_started) + halt_dma(ms); + if (mr->fifo_count) { + out_8(&mr->sequence, SEQ_FLUSHFIFO); + udelay(1); + } + + ms->msgphase = msg_none; + switch (phase) { + case BP_DATAIN: + ms->data_goes_out = 0; + ms->phase = dataing; + break; + case BP_DATAOUT: + ms->data_goes_out = 1; + ms->phase = dataing; + break; + case BP_COMMAND: + ms->phase = commanding; + break; + case BP_STATUS: + ms->phase = statusing; + break; + case BP_MSGIN: + ms->msgphase = msg_in; + ms->n_msgin = 0; + break; + case BP_MSGOUT: + ms->msgphase = msg_out; + if (ms->n_msgout == 0) { + if (ms->last_n_msgout == 0) { + printk(KERN_DEBUG "mesh: no msg to repeat\n"); + ms->msgout[0] = NOP; + ms->last_n_msgout = 1; + } + ms->n_msgout = ms->last_n_msgout; + } + break; + default: + printk(KERN_DEBUG "mesh: unknown scsi phase %x\n", phase); + ms->current_req->result = DID_ERROR << 16; + mesh_done(ms); + return; + } + + start_phase(ms); +} + +static void +reselected(struct mesh_state *ms) +{ + volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp; + int b, t; + + switch (ms->phase) { + case idle: + case arbitrating: + break; + case busfreeing: + ms->phase = reselecting; + mesh_done(ms); + cmd = NULL; + break; + case disconnecting: + cmd = NULL; + break; + default: + printk(KERN_ERR "mesh: reselected in phase %d/%d\n", + ms->msgphase, ms->phase); + } + if (cmd) { + /* put the command back on the queue */ + cmd->host_scribble = (void *) ms->request_q; + if (ms->request_q == NULL) + ms->request_qtail = cmd; + ms->request_q = cmd; + tp = &ms->tgts[cmd->target]; + tp->current_req = NULL; + ms->current_req = NULL; + } + + /* + * Find out who reselected us. + */ + if (mr->fifo_count == 0) { + printk(KERN_ERR "mesh: reselection but nothing in fifo?\n"); + return; + } + /* get the last byte in the fifo */ + do { + b = in_8(&mr->fifo); + } while (in_8(&mr->fifo_count)); + for (t = 0; t < 8; ++t) + if ((b & (1 << t)) != 0 && t != ms->host->this_id) + break; + if (b != (1 << t) + (1 << ms->host->this_id)) { + printk(KERN_ERR "mesh: bad reselection data %x\n", b); + return; + } + + /* + * Set up to continue with that target's transfer. + */ + tp = &ms->tgts[t]; + if (ALLOW_DEBUG(t)) { + printk(KERN_DEBUG "mesh: reselected by target %d\n", t); + printk(KERN_DEBUG "mesh: saved_ptr=%x phase=%d cmd=%p\n", + tp->saved_ptr, tp->phase, tp->current_req); + } + if (tp->current_req == NULL) { + printk(KERN_ERR "mesh: reselected by tgt %d but no cmd!\n", t); + return; + } + ms->current_req = tp->current_req; + ms->phase = tp->phase; + ms->msgphase = msg_in; + ms->data_goes_out = tp->data_goes_out; + ms->data_ptr = tp->saved_ptr; + ms->conn_tgt = t; + ms->dma_started = 0; + ms->n_msgout = 0; + ms->last_n_msgout = 0; + out_8(&mr->sync_params, tp->sync_params); + start_phase(ms); +} + +static void +handle_reset(struct mesh_state *ms) +{ + int tgt; + struct mesh_target *tp; + Scsi_Cmnd *cmd; + volatile struct mesh_regs *mr = ms->mesh; + + for (tgt = 0; tgt < 8; ++tgt) { + tp = &ms->tgts[tgt]; + if ((cmd = tp->current_req) != NULL) { + cmd->result = DID_RESET << 16; + tp->current_req = NULL; + mesh_completed(ms, cmd); + } + ms->tgts[tgt].sdtr_state = do_sdtr; + ms->tgts[tgt].sync_params = ASYNC_PARAMS; + } + ms->current_req = NULL; + while ((cmd = ms->request_q) != NULL) { + ms->request_q = (Scsi_Cmnd *) cmd->host_scribble; + cmd->result = DID_RESET << 16; + mesh_completed(ms, cmd); + } + ms->phase = idle; + out_8(&mr->sync_params, ASYNC_PARAMS); +} + +static void +mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) +{ + struct mesh_state *ms = (struct mesh_state *) dev_id; + volatile struct mesh_regs *mr = ms->mesh; + Scsi_Cmnd *cmd = ms->current_req; + int stat, exc, err, intr; + +#if 0 + if (DEBUG_TARGET(cmd)) + printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x phase=%d msgphase=%d\n", + mr->bus_status0, mr->interrupt, mr->exception, mr->error, ms->phase, ms->msgphase); +#endif + while ((intr = in_8(&mr->interrupt)) != 0) { + if (intr & INT_ERROR) { + stat = DID_BAD_INTR << 16; + err = in_8(&mr->error); + exc = in_8(&mr->exception); + out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE); + if (err & ERR_SCSIRESET) { + /* SCSI bus was reset */ + printk(KERN_INFO "mesh: SCSI bus reset detected: " + "waiting for end..."); + while ((mr->bus_status1 & BS1_RST) != 0) + udelay(1); + printk("done\n"); + handle_reset(ms); + /* request_q is empty, no point in mesh_start() */ + continue; + } else if (err & ERR_UNEXPDISC) { + /* Unexpected disconnect */ + printk(KERN_WARNING "mesh: target %d aborted\n", + ms->conn_tgt); + stat = DID_ABORT << 16; + } else if (err & ERR_PARITY) { + printk(KERN_ERR "mesh: parity error\n"); + stat = DID_PARITY << 16; + } else if ((err & ERR_SEQERR) && (exc & EXC_RESELECTED) + && ms->phase == arbitrating) { + /* This can happen if we issue a command to + get the bus just after the target + reselects us. */ + static int mesh_resel_seqerr; + mesh_resel_seqerr++; + reselected(ms); + continue; + } else { + printk(KERN_ERR "mesh: error %x (exc = %x)\n", + err, exc); + mesh_dump_regs(ms); + } + if (cmd != 0) { + cmd->result = stat; + mesh_done(ms); + } + + } else if (intr & INT_EXCEPTION) { + exc = in_8(&mr->exception); + out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE); + if (exc & EXC_RESELECTED) { + static int mesh_resel_exc; + mesh_resel_exc++; + reselected(ms); + } else if (cmd && exc == EXC_ARBLOST + && ms->phase == arbitrating) { + printk(KERN_DEBUG "mesh: lost arbitration\n"); + cmd->result = DID_BUS_BUSY << 16; + mesh_done(ms); + } else if (cmd && exc == EXC_SELTO && ms->phase == selecting) { + /* selection timed out */ + cmd->result = DID_BAD_TARGET << 16; + mesh_done(ms); + } else if (cmd && exc == EXC_PHASEMM + && (mr->bus_status0 & BS0_REQ) != 0) { + /* target wants to do something different: + find out what it wants and do it. */ + phase_mismatch(ms); + } else { + printk(KERN_ERR "mesh: can't cope with exception %x\n", + exc); + cmd->result = DID_ERROR << 16; + mesh_done(ms); + } + + } else if (intr & INT_CMDDONE) { + out_8(&mr->interrupt, INT_CMDDONE); + cmd_complete(ms); + } + } +} + +static void +handle_msgin(struct mesh_state *ms) +{ + int i; + Scsi_Cmnd *cmd = ms->current_req; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + + if (ms->n_msgin == 0) + return; + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "got %d message bytes:", ms->n_msgin); + for (i = 0; i < ms->n_msgin; ++i) + printk(" %x", ms->msgin[i]); + printk("\n"); + } + + ms->expect_reply = 0; + ms->n_msgout = 0; + if (ms->n_msgin < msgin_length(ms)) + goto reject; + if (cmd) + cmd->SCp.Message = ms->msgin[0]; + switch (ms->msgin[0]) { + case COMMAND_COMPLETE: + break; + case EXTENDED_MESSAGE: + switch (ms->msgin[2]) { + case EXTENDED_MODIFY_DATA_POINTER: + ms->data_ptr += (ms->msgin[3] << 24) + ms->msgin[6] + + (ms->msgin[4] << 16) + (ms->msgin[5] << 8); + break; + case EXTENDED_SDTR: + if (tp->sdtr_state != sdtr_sent) { + /* reply with an SDTR */ + add_sdtr_msg(ms); + /* limit period to at least his value, + offset to no more than his */ + if (ms->msgout[3] < ms->msgin[3]) + ms->msgout[3] = ms->msgin[3]; + if (ms->msgout[4] > ms->msgin[4]) + ms->msgout[4] = ms->msgin[4]; + set_sdtr(ms, ms->msgout[3], ms->msgout[4]); + ms->msgphase = msg_out; + } else { + set_sdtr(ms, ms->msgin[3], ms->msgin[4]); + } + break; + default: + goto reject; + } + break; + case SAVE_POINTERS: + tp->saved_ptr = ms->data_ptr; + break; + case RESTORE_POINTERS: + ms->data_ptr = tp->saved_ptr; + break; + case DISCONNECT: + tp->phase = ms->phase; + tp->data_goes_out = ms->data_goes_out; + ms->phase = disconnecting; + break; + case ABORT: + break; + case MESSAGE_REJECT: + if (tp->sdtr_state == sdtr_sent) + set_sdtr(ms, 0, 0); + break; + case NOP: + break; + default: + if (cmd && IDENTIFY_BASE <= ms->msgin[0] + && ms->msgin[0] <= IDENTIFY_BASE + 7) { + i = ms->msgin[0] - IDENTIFY_BASE; + if (i != cmd->lun) + printk(KERN_WARNING "mesh: lun mismatch " + "(%d != %d) on reselection from " + "target %d\n", i, cmd->lun, + ms->conn_tgt); + break; + } + goto reject; + } + return; + + reject: + printk(KERN_WARNING "mesh: rejecting message %x from target %d\n", + ms->msgin[0], ms->conn_tgt); + ms->msgout[0] = MESSAGE_REJECT; + ms->n_msgout = 1; + ms->msgphase = msg_out; +} + +static void +mesh_done(struct mesh_state *ms) +{ + Scsi_Cmnd *cmd; + struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; + + cmd = ms->current_req; + if (DEBUG_TARGET(cmd)) { + printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n", + cmd->result, ms->data_ptr, cmd->request_bufflen); + if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3) + && cmd->request_buffer != 0) { + unsigned char *b = cmd->request_buffer; + printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n", + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } + } + tp->current_req = 0; + cmd->SCp.this_residual -= ms->data_ptr; + ms->current_req = NULL; + mesh_completed(ms, cmd); + if (ms->phase != reselecting) { + ms->phase = idle; + mesh_start(ms); + } +} + +static void +mesh_completed(struct mesh_state *ms, Scsi_Cmnd *cmd) +{ + if (ms->completed_q == NULL) + ms->completed_q = cmd; + else + ms->completed_qtail->host_scribble = (void *) cmd; + ms->completed_qtail = cmd; + cmd->host_scribble = NULL; + queue_task(&ms->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * Set up DMA commands for transferring data. + */ +static void +set_dma_cmds(struct mesh_state *ms, Scsi_Cmnd *cmd) +{ + int i, dma_cmd, total, off, dtot; + struct scatterlist *scl; + struct dbdma_cmd *dcmds; + + dma_cmd = ms->data_goes_out? OUTPUT_MORE: INPUT_MORE; + dcmds = ms->dma_cmds; + dtot = 0; + cmd->SCp.this_residual = cmd->request_bufflen; + if (cmd->use_sg > 0) { + total = 0; + scl = (struct scatterlist *) cmd->buffer; + off = ms->data_ptr; + for (i = 0; i < cmd->use_sg; ++i, ++scl) { + total += scl->length; + if (off >= scl->length) { + off -= scl->length; + continue; + } + if (scl->length > 0xffff) + panic("mesh: scatterlist element >= 64k"); + st_le16(&dcmds->req_count, scl->length - off); + st_le16(&dcmds->command, dma_cmd); + st_le32(&dcmds->phy_addr, + virt_to_phys(scl->address) + off); + dcmds->xfer_status = 0; + ++dcmds; + dtot += scl->length - off; + off = 0; + } + } else if (ms->data_ptr < cmd->request_bufflen) { + dtot = cmd->request_bufflen - ms->data_ptr; + if (dtot > 0xffff) + panic("mesh: transfer size >= 64k"); + st_le16(&dcmds->req_count, dtot); + st_le32(&dcmds->phy_addr, + virt_to_phys(cmd->request_buffer) + ms->data_ptr); + dcmds->xfer_status = 0; + ++dcmds; + } + if (dtot == 0) { + /* Either the target has overrun our buffer, + or the caller didn't provide a buffer. */ + static char mesh_extra_buf[64]; + + if (cmd->request_bufflen != 0) + printk(KERN_DEBUG "mesh: target %d overrun, " + "data_ptr=%x total=%x goes_out=%d\n", + ms->conn_tgt, ms->data_ptr, + cmd->request_bufflen, ms->data_goes_out); + dtot = sizeof(mesh_extra_buf); + st_le16(&dcmds->req_count, dtot); + st_le32(&dcmds->phy_addr, virt_to_phys(mesh_extra_buf)); + dcmds->xfer_status = 0; + ++dcmds; + } + dma_cmd += OUTPUT_LAST - OUTPUT_MORE; + st_le16(&dcmds[-1].command, dma_cmd); + memset(dcmds, 0, sizeof(*dcmds)); + st_le16(&dcmds->command, DBDMA_STOP); + ms->dma_count = dtot; +} + +static void +halt_dma(struct mesh_state *ms) +{ + volatile struct dbdma_regs *md = ms->dma; + volatile struct mesh_regs *mr = ms->mesh; + int t, nb; + + if (!ms->data_goes_out) { + /* wait a little while until the fifo drains */ + t = 50; + while (t > 0 && mr->fifo_count != 0 + && (in_le32(&md->status) & ACTIVE) != 0) { + --t; + udelay(1); + } + } + out_le32(&md->control, RUN << 16); /* turn off RUN bit */ + nb = (mr->count_hi << 8) + mr->count_lo; + if (ms->data_goes_out) + nb += mr->fifo_count; + /* nb is the number of bytes not yet transferred + to/from the target. */ + ms->data_ptr -= nb; + if (ms->data_ptr < 0) { + printk(KERN_ERR "mesh: halt_dma: data_ptr=%d (nb=%d, ms=%p)\n", + ms->data_ptr, nb, ms); + ms->data_ptr = 0; + } + ms->dma_started = 0; +} + +/* + * Work out whether we expect data to go out from the host adaptor or into it. + * (If this information is available from somewhere else in the scsi + * code, somebody please let me know :-) + */ +static int +data_goes_out(Scsi_Cmnd *cmd) +{ + switch (cmd->cmnd[0]) { + case MODE_SELECT: + case MODE_SELECT_10: + case WRITE_6: + case WRITE_10: + case WRITE_12: /* any others? */ + return 1; + default: + return 0; + } +} diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/mesh.h linux/drivers/scsi/mesh.h --- v2.1.50/linux/drivers/scsi/mesh.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mesh.h Sat Aug 16 09:53:08 1997 @@ -0,0 +1,159 @@ +/* + * mesh.h: definitions for the driver for the MESH SCSI bus adaptor + * (Macintosh Enhanced SCSI Hardware) found on Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + */ +#ifndef _MESH_H +#define _MESH_H + +extern struct proc_dir_entry proc_scsi_mesh; + +int mesh_detect(Scsi_Host_Template *); +int mesh_command(Scsi_Cmnd *); +int mesh_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int mesh_abort(Scsi_Cmnd *); +int mesh_reset(Scsi_Cmnd *, unsigned int); + +#define SCSI_MESH { \ + NULL, /* next */ \ + NULL, /* usage_count */ \ + &proc_scsi_mesh, /* proc_dir */ \ + NULL, /* proc_info */ \ + "MESH", /* name */ \ + mesh_detect, /* detect */ \ + NULL, /* release */ \ + NULL, /* info */ \ + mesh_command, /* command */ \ + mesh_queue, /* queuecommand */ \ + mesh_abort, /* abort */ \ + mesh_reset, /* reset */ \ + NULL, /* slave_attach */ \ + NULL, /* bios_param */ \ + 20, /* can_queue */ \ + 7, /* this_id */ \ + SG_ALL, /* sg_tablesize */ \ + 2, /* cmd_per_lun */ \ + 0, /* present */ \ + 0, /* unchecked_isa_dma */ \ + DISABLE_CLUSTERING, /* use_clustering */ \ +} + +/* + * Registers in the MESH controller. + */ + +struct mesh_regs { + unsigned char count_lo; + char pad0[15]; + unsigned char count_hi; + char pad1[15]; + unsigned char fifo; + char pad2[15]; + unsigned char sequence; + char pad3[15]; + unsigned char bus_status0; + char pad4[15]; + unsigned char bus_status1; + char pad5[15]; + unsigned char fifo_count; + char pad6[15]; + unsigned char exception; + char pad7[15]; + unsigned char error; + char pad8[15]; + unsigned char intr_mask; + char pad9[15]; + unsigned char interrupt; + char pad10[15]; + unsigned char source_id; + char pad11[15]; + unsigned char dest_id; + char pad12[15]; + unsigned char sync_params; + char pad13[15]; + unsigned char mesh_id; + char pad14[15]; + unsigned char sel_timeout; + char pad15[15]; +}; + +/* Bits in the sequence register. */ +#define SEQ_DMA_MODE 0x80 /* use DMA for data transfer */ +#define SEQ_TARGET 0x40 /* put the controller into target mode */ +#define SEQ_ATN 0x20 /* assert ATN signal */ +#define SEQ_ACTIVE_NEG 0x10 /* use active negation on REQ/ACK */ +#define SEQ_CMD 0x0f /* command bits: */ +#define SEQ_ARBITRATE 1 /* get the bus */ +#define SEQ_SELECT 2 /* select a target */ +#define SEQ_COMMAND 3 /* send a command */ +#define SEQ_STATUS 4 /* receive status */ +#define SEQ_DATAOUT 5 /* send data */ +#define SEQ_DATAIN 6 /* receive data */ +#define SEQ_MSGOUT 7 /* send a message */ +#define SEQ_MSGIN 8 /* receive a message */ +#define SEQ_BUSFREE 9 /* look for bus free */ +#define SEQ_ENBPARITY 0x0a /* enable parity checking */ +#define SEQ_DISPARITY 0x0b /* disable parity checking */ +#define SEQ_ENBRESEL 0x0c /* enable reselection */ +#define SEQ_DISRESEL 0x0d /* disable reselection */ +#define SEQ_RESETMESH 0x0e /* reset the controller */ +#define SEQ_FLUSHFIFO 0x0f /* clear out the FIFO */ + +/* Bits in the bus_status0 and bus_status1 registers: + these correspond directly to the SCSI bus control signals. */ +#define BS0_REQ 0x20 +#define BS0_ACK 0x10 +#define BS0_ATN 0x08 +#define BS0_MSG 0x04 +#define BS0_CD 0x02 +#define BS0_IO 0x01 +#define BS1_RST 0x80 +#define BS1_BSY 0x40 +#define BS1_SEL 0x20 + +/* Bus phases defined by the bits in bus_status0 */ +#define BS0_PHASE (BS0_MSG+BS0_CD+BS0_IO) +#define BP_DATAOUT 0 +#define BP_DATAIN BS0_IO +#define BP_COMMAND BS0_CD +#define BP_STATUS (BS0_CD+BS0_IO) +#define BP_MSGOUT (BS0_MSG+BS0_CD) +#define BP_MSGIN (BS0_MSG+BS0_CD+BS0_IO) + +/* Bits in the exception register. */ +#define EXC_SELWATN 0x20 /* (as target) we were selected with ATN */ +#define EXC_SELECTED 0x10 /* (as target) we were selected w/o ATN */ +#define EXC_RESELECTED 0x08 /* (as initiator) we were reselected */ +#define EXC_ARBLOST 0x04 /* we lost arbitration */ +#define EXC_PHASEMM 0x02 /* SCSI phase mismatch */ +#define EXC_SELTO 0x01 /* selection timeout */ + +/* Bits in the error register */ +#define ERR_UNEXPDISC 0x40 /* target unexpectedly disconnected */ +#define ERR_SCSIRESET 0x20 /* SCSI bus got reset on us */ +#define ERR_SEQERR 0x10 /* we did something the chip didn't like */ +#define ERR_PARITY 0x01 /* parity error was detected */ + +/* Bits in the interrupt and intr_mask registers */ +#define INT_ERROR 0x04 /* error interrupt */ +#define INT_EXCEPTION 0x02 /* exception interrupt */ +#define INT_CMDDONE 0x01 /* command done interrupt */ + +/* Fields in the sync_params register */ +#define SYNC_OFF(x) ((x) >> 4) /* offset field */ +#define SYNC_PER(x) ((x) & 0xf) /* period field */ +#define SYNC_PARAMS(o, p) (((o) << 4) | (p)) +#define ASYNC_PARAMS 2 /* sync_params value for async xfers */ + +/* + * Assuming a clock frequency of 50MHz: + * + * The transfer period with SYNC_PER(sync_params) == x + * is (x + 2) * 40ns, except that x == 0 gives 100ns. + * + * The units of the sel_timeout register are 10ms. + */ + + +#endif /* _MESH_H */ diff -u --recursive --new-file v2.1.50/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.1.50/linux/drivers/scsi/sr.c Mon Apr 7 11:35:30 1997 +++ linux/drivers/scsi/sr.c Thu Aug 14 20:55:14 1997 @@ -1007,12 +1007,13 @@ for(cpnt = scsi_CDs, i=0; idevice == SDp) { kdev_t devi = MKDEV(MAJOR_NR, i); + struct super_block * sb = get_super(devi); /* * Since the cdrom is read-only, no need to sync the device. * We should be kind to our buffer cache, however. */ - invalidate_inodes(devi); + if (sb) invalidate_inodes(sb); invalidate_buffers(devi); /* diff -u --recursive --new-file v2.1.50/linux/fs/Config.in linux/fs/Config.in --- v2.1.50/linux/fs/Config.in Thu Jul 17 10:06:06 1997 +++ linux/fs/Config.in Sat Aug 16 09:53:08 1997 @@ -60,5 +60,6 @@ bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL fi +bool 'Macintosh partition map support' CONFIG_MAC_PARTITION endmenu diff -u --recursive --new-file v2.1.50/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.1.50/linux/fs/affs/file.c Thu Jul 17 10:06:06 1997 +++ linux/fs/affs/file.c Fri Aug 15 12:51:03 1997 @@ -629,7 +629,7 @@ inode->i_size = pos; inode->i_mtime = inode->i_ctime = CURRENT_TIME; filp->f_pos = pos; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(ino); return written; } @@ -717,7 +717,7 @@ inode->i_size = pos; filp->f_pos = pos; inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(ino); return written; } diff -u --recursive --new-file v2.1.50/linux/fs/affs/inode.c linux/fs/affs/inode.c --- v2.1.50/linux/fs/affs/inode.c Thu Jul 17 10:06:06 1997 +++ linux/fs/affs/inode.c Fri Aug 15 12:51:03 1997 @@ -595,11 +595,11 @@ s->s_dev = dev; s->s_op = &affs_sops; - s->s_mounted = iget(s,root_block); + s->s_root = d_alloc_root(iget(s,root_block),NULL); s->s_dirt = 1; unlock_super(s); - if (!(s->s_mounted)) { + if (!(s->s_root)) { s->s_dev = 0; printk(KERN_ERR "AFFS: get root inode failed\n"); MOD_DEC_USE_COUNT; @@ -609,9 +609,9 @@ /* create data zones if the fs is mounted r/w */ if (!(s->s_flags & MS_RDONLY)) { - ROOT_END(s->u.affs_sb.s_root_bh->b_data,s->s_mounted)->bm_flag = 0; + ROOT_END(s->u.affs_sb.s_root_bh->b_data,s->s_root->d_inode)->bm_flag = 0; secs_to_datestamp(CURRENT_TIME,&ROOT_END(s->u.affs_sb.s_root_bh->b_data, - s->s_mounted)->disk_altered); + s->s_root->d_inode)->disk_altered); affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5); mark_buffer_dirty(s->u.affs_sb.s_root_bh,1); affs_make_zones(s); @@ -803,7 +803,6 @@ pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino); - inode->i_dirt = 0; if (!inode->i_nlink) return; if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) { @@ -909,7 +908,7 @@ inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; - inode->i_dirt = 1; + mark_inode_dirty(inode); inode->i_ino = block; inode->i_op = NULL; inode->i_blocks = 0; @@ -1012,7 +1011,7 @@ FILE_END(link_bh->b_data,link)->link_chain = ntohl(inode->i_ino); affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5); link->i_version = ++event; - link->i_dirt = 1; + mark_inode_dirty(link); mark_buffer_dirty(link_bh,1); } affs_fix_checksum(AFFS_I2BSIZE(inode),inode_bh->b_data,5); @@ -1021,8 +1020,8 @@ dir->i_mtime = dir->i_atime = dir->i_ctime = CURRENT_TIME; unlock_super(inode->i_sb); - dir->i_dirt = 1; - inode->i_dirt = 1; + mark_inode_dirty(dir); + mark_inode_dirty(inode); mark_buffer_dirty(dir_bh,1); mark_buffer_dirty(inode_bh,1); diff -u --recursive --new-file v2.1.50/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.50/linux/fs/affs/namei.c Thu Jul 17 10:06:06 1997 +++ linux/fs/affs/namei.c Fri Aug 15 12:51:03 1997 @@ -205,10 +205,10 @@ goto unlink_done; inode->i_nlink=0; - inode->i_dirt=1; + mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_version = ++event; - dir->i_dirt=1; + mark_inode_dirty(dir); unlink_done: affs_brelse(bh); iput(inode); @@ -244,7 +244,7 @@ if (error) { iput(dir); inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return -ENOSPC; } @@ -286,7 +286,7 @@ if (error) { iput(dir); inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return error; } @@ -356,10 +356,10 @@ goto rmdir_done; inode->i_nlink=0; - inode->i_dirt=1; + mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_version = ++event; - dir->i_dirt=1; + mark_inode_dirty(dir); rmdir_done: iput(dir); iput(inode); @@ -392,7 +392,7 @@ if (!bh) { iput(dir); inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); return -EIO; } @@ -426,7 +426,7 @@ *p = 0; mark_buffer_dirty(bh,1); affs_brelse(bh); - inode->i_dirt = 1; + mark_inode_dirty(inode); bh = affs_find_entry(dir,name,len,&tmp); if (bh) { inode->i_nlink = 0; @@ -438,7 +438,7 @@ i = affs_add_entry(dir,NULL,inode,name,len,ST_SOFTLINK); if (i) { inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); iput(inode); affs_brelse(bh); iput(dir); @@ -497,7 +497,7 @@ error = affs_add_entry(dir,oldinode,inode,name,len,ST_LINKFILE); if (error) { inode->i_nlink = 0; - inode->i_dirt = 1; + mark_inode_dirty(inode); } iput(dir); iput(inode); @@ -616,9 +616,9 @@ goto retry; mark_buffer_dirty(new_bh,1); new_dir->i_version = ++event; - new_dir->i_dirt = 1; + mark_inode_dirty(new_dir); new_inode->i_nlink = 0; - new_inode->i_dirt = 1; + mark_inode_dirty(new_inode); } retval = affs_fix_hash_pred(old_dir,affs_hash_name(old_name,old_len,AFFS_I2FSTYPE(old_dir), AFFS_I2HSIZE(old_dir)) + 6,old_ino, @@ -632,8 +632,8 @@ new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; new_dir->i_version = ++event; old_dir->i_version = ++event; - new_dir->i_dirt = 1; - old_dir->i_dirt = 1; + mark_inode_dirty(new_dir); + mark_inode_dirty(old_dir); mark_buffer_dirty(old_bh,1); end_rename: @@ -704,7 +704,7 @@ ofinode->i_size = inode->i_size; ofinode->i_uid = inode->i_uid; ofinode->i_gid = inode->i_gid; - ofinode->i_dirt = 1; + mark_inode_dirty(ofinode); link_key = ofinode->i_ino; /* Let all remaining links point to the new file */ @@ -722,7 +722,7 @@ "Inode %d in link chain is not a link", key); ofinode->u.affs_i.i_original = link_key; - ofinode->i_dirt = 1; + mark_inode_dirty(ofinode); FILE_END(nbh->b_data,inode)->original = htonl(link_key); } else affs_error(inode->i_sb,"fixup","Cannot read block %d",key); diff -u --recursive --new-file v2.1.50/linux/fs/autofs/inode.c linux/fs/autofs/inode.c --- v2.1.50/linux/fs/autofs/inode.c Mon Aug 4 16:25:38 1997 +++ linux/fs/autofs/inode.c Fri Aug 15 10:01:29 1997 @@ -141,6 +141,9 @@ struct super_block *autofs_read_super(struct super_block *s, void *data, int silent) { + struct inode * root_inode; + struct dentry * root; + struct file * pipe; int pipefd; struct autofs_sb_info *sbi; int minproto, maxproto; @@ -148,12 +151,13 @@ MOD_INC_USE_COUNT; lock_super(s); + /* Super block already completed? */ + if (s->s_root) + goto out_unlock; + sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL); - if ( !sbi ) { - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; - } + if ( !sbi ) + goto fail_unlock; DPRINTK(("autofs: starting up, sbi = %p\n",sbi)); s->u.generic_sbp = sbi; @@ -169,50 +173,112 @@ s->s_blocksize_bits = 10; s->s_magic = AUTOFS_SUPER_MAGIC; s->s_op = &autofs_sops; - unlock_super(s); - s->s_root = d_alloc_root(iget(s, AUTOFS_ROOT_INO), NULL); - if (!s->s_root) { - printk("autofs: get root inode failed\n"); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; - } + s->s_root = NULL; + unlock_super(s); /* shouldn't we keep it locked a while longer? */ + + /* + * Get the root inode and dentry, but defer checking for errors. + */ + root_inode = iget(s, AUTOFS_ROOT_INO); + root = d_alloc_root(root_inode, NULL); + pipe = NULL; + + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_dput; - if ( parse_options(data,&pipefd,&s->s_root->d_inode->i_uid,&s->s_root->d_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) { + if (!root) + goto fail_iput; + + /* Can this call block? */ + if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) { printk("autofs: called with bogus options\n"); - dput(s->s_root); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; + goto fail_dput; } - if ( minproto > AUTOFS_PROTO_VERSION || maxproto < AUTOFS_PROTO_VERSION ) { + /* Couldn't this be tested earlier? */ + if ( minproto > AUTOFS_PROTO_VERSION || + maxproto < AUTOFS_PROTO_VERSION ) { printk("autofs: kernel does not match daemon version\n"); - dput(s->s_root); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; + goto fail_dput; } DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp)); - sbi->pipe = fget(pipefd); - if ( !sbi->pipe || !sbi->pipe->f_op || !sbi->pipe->f_op->write ) { - if ( sbi->pipe ) { - fput(sbi->pipe); - printk("autofs: pipe file descriptor does not contain proper ops\n"); - } else { - printk("autofs: could not open pipe file descriptor\n"); - } - dput(s->s_root); - kfree(sbi); - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; + pipe = fget(pipefd); + /* + * Check whether somebody else completed the super block. + */ + if (s->s_root) + goto out_fput; + + if ( !pipe ) { + printk("autofs: could not open pipe file descriptor\n"); + goto fail_dput; } + if ( !pipe->f_op || !pipe->f_op->write ) + goto fail_fput; + sbi->pipe = pipe; + + /* + * Success! Install the root dentry now to indicate completion. + */ + s->s_root = root; return s; + + /* + * Success ... somebody else completed the super block for us. + */ +out_unlock: + unlock_super(s); + goto out_dec; +out_fput: + if (pipe) + fput(pipe); +out_dput: + if (root) + dput(root); + else + iput(root_inode); +out_dec: + MOD_DEC_USE_COUNT; + return s; + + /* + * Failure ... clear the s_dev slot and clean up. + */ +fail_fput: + printk("autofs: pipe file descriptor does not contain proper ops\n"); + /* + * fput() can block, so we clear the super block first. + */ + s->s_dev = 0; + fput(pipe); + /* fall through */ +fail_dput: + /* + * dput() can block, so we clear the super block first. + */ + s->s_dev = 0; + dput(root); + goto fail_free; +fail_iput: + printk("autofs: get root dentry failed\n"); + /* + * iput() can block, so we clear the super block first. + */ + s->s_dev = 0; + iput(root_inode); +fail_free: + kfree(sbi); + goto fail_dec; +fail_unlock: + unlock_super(s); +fail_dec: + s->s_dev = 0; + MOD_DEC_USE_COUNT; + return NULL; } static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) diff -u --recursive --new-file v2.1.50/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.1.50/linux/fs/binfmt_elf.c Sun Jul 20 20:41:58 1997 +++ linux/fs/binfmt_elf.c Sat Aug 16 09:55:26 1997 @@ -115,15 +115,17 @@ /* * Force 16 byte _final_ alignment here for generality. + * Leave an extra 16 bytes free so that on the PowerPC we + * can move the aux table up to start on a 16-byte boundary. */ - sp = (elf_addr_t *) (~15UL & (unsigned long) p); + sp = (elf_addr_t *) ((~15UL & (unsigned long) p) - 16UL); csp = sp; csp -= exec ? DLINFO_ITEMS*2 : 2; csp -= envc+1; csp -= argc+1; csp -= (!ibcs ? 3 : 1); /* argc itself */ if ((unsigned long)csp & 15UL) { - sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp); + sp -= ((unsigned long)csp & 15UL) / sizeof(*sp); } /* diff -u --recursive --new-file v2.1.50/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.50/linux/fs/dcache.c Thu Aug 14 20:49:17 1997 +++ linux/fs/dcache.c Thu Aug 14 21:53:08 1997 @@ -34,7 +34,7 @@ static struct list_head dentry_hashtable[D_HASHSIZE]; static LIST_HEAD(dentry_unused); -void d_free(struct dentry *dentry) +static inline void d_free(struct dentry *dentry) { kfree(dentry->d_name.name); kfree(dentry); @@ -165,10 +165,10 @@ memcpy(str, name->name, name->len); str[name->len] = 0; - dentry->d_count = 0; + dentry->d_count = 1; dentry->d_flags = 0; dentry->d_inode = NULL; - dentry->d_parent = parent; + dentry->d_parent = dget(parent); dentry->d_mounts = dentry; dentry->d_covers = dentry; INIT_LIST_HEAD(&dentry->d_hash); @@ -207,7 +207,6 @@ if (root_inode) { res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); res->d_parent = res; - res->d_count = 1; d_instantiate(res, root_inode); } return res; @@ -238,13 +237,13 @@ if (parent->d_op && parent->d_op->d_compare) { if (parent->d_op->d_compare(parent, &dentry->d_name, name)) continue; - return dentry; + } else { + if (dentry->d_name.len != len) + continue; + if (memcmp(dentry->d_name.name, str, len)) + continue; } - if (dentry->d_name.len != len) - continue; - if (memcmp(dentry->d_name.name, str, len)) - continue; - return dentry; + return dget(dentry->d_mounts); } return NULL; } @@ -329,7 +328,7 @@ void d_add(struct dentry * entry, struct inode * inode) { - struct dentry * parent = dget(entry->d_parent); + struct dentry * parent = entry->d_parent; list_add(&entry->d_hash, d_hash(parent, entry->d_name.hash)); d_instantiate(entry, inode); diff -u --recursive --new-file v2.1.50/linux/fs/exec.c linux/fs/exec.c --- v2.1.50/linux/fs/exec.c Sun Jul 20 20:41:58 1997 +++ linux/fs/exec.c Sat Aug 16 09:55:26 1997 @@ -396,7 +396,7 @@ *mm = *current->mm; init_new_context(mm); mm->def_flags = 0; /* should future lockings be kept? */ - mm->cpu_vm_mask = (1 << smp_processor_id()); + mm->cpu_vm_mask = (1UL << smp_processor_id()); mm->count = 1; mm->mmap = mm->mmap_cache = NULL; mm->total_vm = 0; diff -u --recursive --new-file v2.1.50/linux/fs/isofs/namei.c linux/fs/isofs/namei.c --- v2.1.50/linux/fs/isofs/namei.c Thu Jul 17 10:06:07 1997 +++ linux/fs/isofs/namei.c Fri Aug 15 12:19:17 1997 @@ -63,12 +63,14 @@ { unsigned long bufsize = ISOFS_BUFFER_SIZE(dir); unsigned char bufbits = ISOFS_BUFFER_BITS(dir); - unsigned int block, i, f_pos, offset, inode_number; + unsigned int block, i, f_pos, offset, + inode_number = 0; /* shut gcc up */ struct buffer_head * bh; unsigned int old_offset; int dlen, rrflag, match; char * dpnt; - struct iso_directory_record * de; + struct iso_directory_record * de = NULL; /* shut gcc up */ + char de_not_in_buf = 0; /* true if de is in kmalloc'd memory */ char c; *ino = 0; @@ -84,17 +86,36 @@ if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL; while (f_pos < dir->i_size) { - de = (struct iso_directory_record *) (bh->b_data + offset); - inode_number = (block << bufbits) + (offset & (bufsize - 1)); - /* If byte is zero, this is the end of file, or time to move to - the next sector. Usually 2048 byte boundaries. */ + /* if de is in kmalloc'd memory, do not point to the + next de, instead we will move to the next sector */ + if(!de_not_in_buf) { + de = (struct iso_directory_record *) + (bh->b_data + offset); + inode_number = (block << bufbits) + + (offset & (bufsize - 1)); + } + + /* If byte is zero, or we had to fetch this de past + the end of the buffer, this is the end of file, or + time to move to the next sector. Usually 2048 byte + boundaries. */ - if (*((unsigned char *) de) == 0) { + if (*((unsigned char *) de) == 0 || de_not_in_buf) { + if(de_not_in_buf) { + /* james@bpgc.com: Since we slopped + past the end of the last buffer, we + must start some way into the new + one */ + de_not_in_buf = 0; + kfree(de); + offset -= bufsize; + } + else + offset = 0; brelse(bh); - offset = 0; f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1)) - + ISOFS_BLOCK_SIZE); + + ISOFS_BLOCK_SIZE) + offset; if( f_pos >= dir->i_size ) { @@ -111,11 +132,28 @@ offset += *((unsigned char *) de); f_pos += *((unsigned char *) de); - /* Handle case where the directory entry spans two blocks. - Usually 1024 byte boundaries */ + /* james@bpgc.com: new code to handle case where the + directory entry spans two blocks. Usually 1024 + byte boundaries */ if (offset >= bufsize) { - printk("Directory entry extends past end of iso9660 block\n"); - return 0; + struct buffer_head *bh_next; + + /* james@bpgc.com: read the next block, and + copy the split de into a newly kmalloc'd + buffer */ + block = isofs_bmap(dir,f_pos>>bufbits); + if (!block || + !(bh_next = bread(dir->i_dev,block,bufsize))) + return NULL; + + de = (struct iso_directory_record *) + kmalloc(offset - old_offset, GFP_KERNEL); + memcpy((char *)de, bh->b_data + old_offset, + bufsize - old_offset); + memcpy((char *)de + bufsize - old_offset, + bh_next->b_data, offset - bufsize); + brelse(bh_next); + de_not_in_buf = 1; } dlen = de->name_len[0]; @@ -161,11 +199,15 @@ find_rock_ridge_relocation(de,dir)); } *ino = inode_number; + if(de_not_in_buf) + kfree(de); return bh; } } out: brelse(bh); + if(de_not_in_buf) + kfree(de); return NULL; } diff -u --recursive --new-file v2.1.50/linux/fs/isofs/symlink.c linux/fs/isofs/symlink.c --- v2.1.50/linux/fs/isofs/symlink.c Mon Jun 16 16:35:57 1997 +++ linux/fs/isofs/symlink.c Fri Aug 15 10:14:21 1997 @@ -19,6 +19,7 @@ #include static int isofs_readlink(struct inode *, char *, int); +static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base); /* * symlinks can't do much... @@ -35,6 +36,7 @@ NULL, /* mknod */ NULL, /* rename */ isofs_readlink, /* readlink */ + isofs_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ @@ -51,7 +53,6 @@ buflen = 1023; pnt = get_rock_ridge_symlink(inode); - iput(inode); if (!pnt) return 0; @@ -62,4 +63,21 @@ i = -EFAULT; kfree(pnt); return i; +} + +static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base) +{ + char * pnt; + + pnt = get_rock_ridge_symlink(inode); + + if(!pnt) { + dput(base); + return ERR_PTR(-ELOOP); + } + + base = lookup_dentry(pnt, base, 1); + + kfree(pnt); + return base; } diff -u --recursive --new-file v2.1.50/linux/fs/namei.c linux/fs/namei.c --- v2.1.50/linux/fs/namei.c Thu Aug 14 20:49:17 1997 +++ linux/fs/namei.c Sat Aug 16 22:27:58 1997 @@ -105,18 +105,6 @@ return res; } -/* - * Kernel pointers have redundant information, so we can use a - * scheme where we can return either an error code or a dentry - * pointer with the same return value. - * - * This should be a per-architecture thing, to allow different - * error and pointer decisions. - */ -#define ERR_PTR(err) ((void *)((long)(err))) -#define PTR_ERR(ptr) ((long)(ptr)) -#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) - inline void putname(char * name) { if (name) { @@ -243,15 +231,12 @@ down(&dir->i_sem); result = d_lookup(parent, name); if (!result) { - int error; - result = d_alloc(parent, name); - result->d_count++; - error = dir->i_op->lookup(dir, result); - result->d_count--; - if (error) { - d_free(result); - result = ERR_PTR(error); - } + struct dentry * dentry = d_alloc(parent, name); + int error = dir->i_op->lookup(dir, dentry); + result = ERR_PTR(error); + if (!error) + result = dget(dentry->d_mounts); + dput(dentry); } up(&dir->i_sem); return result; @@ -271,11 +256,11 @@ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { int validated, (*revalidate)(struct dentry *) = dentry->d_op->d_revalidate; - dentry->d_count++; validated = revalidate(dentry) || d_invalidate(dentry); - dput(dentry); - if (!validated) + if (!validated) { + dput(dentry); dentry = NULL; + } } return dentry; } @@ -302,28 +287,25 @@ result = parent; } } - return result; + return dget(result); } /* In difference to the former version, lookup() no longer eats the dir. */ -static struct dentry * lookup(struct dentry * dir, struct qstr * name) +static inline struct dentry * lookup(struct dentry * dir, struct qstr * name) { struct dentry * result; result = reserved_lookup(dir, name); if (result) - goto done_noerror; + goto done; result = cached_lookup(dir, name); if (result) - goto done_noerror; + goto done; result = real_lookup(dir, name); - if (!IS_ERR(result)) { -done_noerror: - result = dget(result->d_mounts); - } +done: return result; } @@ -538,8 +520,9 @@ if (dir->i_sb && dir->i_sb->dq_op) dir->i_sb->dq_op->initialize(dir, -1); error = dir->i_op->create(dir, dentry, mode); - /* Don't check for write permission */ + /* Don't check for write permission, don't truncate */ acc_mode = 0; + flag &= ~O_TRUNC; } up(&dir->i_sem); if (error) diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c --- v2.1.50/linux/fs/ncpfs/file.c Mon Jun 16 16:35:58 1997 +++ linux/fs/ncpfs/file.c Fri Aug 15 12:51:03 1997 @@ -130,8 +130,8 @@ if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; } - inode->i_dirt = 1; - + mark_inode_dirty(inode); + DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName); return already_read; @@ -192,8 +192,8 @@ } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; - + mark_inode_dirty(inode); + file->f_pos = pos; if (pos > inode->i_size) { diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.1.50/linux/fs/ncpfs/inode.c Thu Jun 26 12:33:39 1997 +++ linux/fs/ncpfs/inode.c Fri Aug 15 12:51:03 1997 @@ -165,7 +165,7 @@ } if ((data->ncp_fd >= NR_OPEN) || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL) - || (!S_ISSOCK(ncp_filp->f_inode->i_mode))) { + || (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))) { printk("ncp_read_super: invalid ncp socket\n"); sb->s_dev = 0; return NULL; @@ -234,8 +234,8 @@ ncp_init_root(server); - if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, - &(server->root))))) { + if (!(sb->s_root = d_alloc_root(iget(sb,ncp_info_ino(server, + &(server->root))),NULL))) { sb->s_dev = 0; printk("ncp_read_super: get root inode failed\n"); goto disconnect; diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c --- v2.1.50/linux/fs/ncpfs/mmap.c Thu Jul 17 10:06:07 1997 +++ linux/fs/ncpfs/mmap.c Fri Aug 15 12:51:03 1997 @@ -32,7 +32,7 @@ static unsigned long ncp_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int no_share) { - struct inode *inode = area->vm_inode; + struct inode *inode = area->vm_dentry->d_inode; unsigned long page; unsigned int clear; unsigned long tmp; @@ -130,7 +130,7 @@ return -EACCES; if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); } vma->vm_dentry = dget(file->f_dentry); diff -u --recursive --new-file v2.1.50/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c --- v2.1.50/linux/fs/ncpfs/sock.c Fri Apr 4 08:52:24 1997 +++ linux/fs/ncpfs/sock.c Fri Aug 15 12:51:03 1997 @@ -102,7 +102,7 @@ struct ncp_reply_header reply; file = server->ncp_filp; - inode = file->f_inode; + inode = file->f_dentry->d_inode; sock = &inode->u.socket_i; if (!sock) { printk("ncp_rpc_call: socki_lookup failed\n"); diff -u --recursive --new-file v2.1.50/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.1.50/linux/fs/nfs/dir.c Thu Aug 14 20:49:17 1997 +++ linux/fs/nfs/dir.c Thu Aug 14 18:10:13 1997 @@ -561,9 +561,6 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct nfs_sattr sattr; - struct nfs_fattr fattr; - struct nfs_fh fhandle; - struct inode * inode; int error; dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n", @@ -590,12 +587,16 @@ if (error) return error; - inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); - if (!inode) - return -EACCES; - nfs_invalidate_dircache(dir); - d_instantiate(dentry, inode); + /* this looks _funny_ doesn't it? But: nfs_proc_symlynk() + * only fills in sattr, not fattr. Thus nfs_fhget() cannot be + * called, it would be pointless, without a valid fattr + * argument. Other possibility: call nfs_proc_lookup() + * HERE. But why? If somebody wants to reference this + * symlink, the cached_lookup() will fail, and + * nfs_proc_symlink() will be called anyway. + */ + d_drop(dentry); return 0; } diff -u --recursive --new-file v2.1.50/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c --- v2.1.50/linux/fs/nfs/symlink.c Mon Jul 7 11:06:36 1997 +++ linux/fs/nfs/symlink.c Thu Aug 14 18:20:15 1997 @@ -61,8 +61,8 @@ copy_to_user(buffer, res, len); put_user('\0', buffer + len); error = len; + kfree(mem); } - kfree(mem); return error; } @@ -81,7 +81,6 @@ if (error) { dput(base); - kfree(mem); return ERR_PTR(error); } path = kmalloc(len + 1, GFP_KERNEL); diff -u --recursive --new-file v2.1.50/linux/fs/nfsd/export.c linux/fs/nfsd/export.c --- v2.1.50/linux/fs/nfsd/export.c Mon Aug 11 14:47:05 1997 +++ linux/fs/nfsd/export.c Sun Aug 17 09:54:07 1997 @@ -248,7 +248,7 @@ finish: /* Release dentry */ - if (err < 0 && dentry) + if (err < 0 && !IS_ERR(dentry)) dput(dentry); /* Unlock hashtable */ diff -u --recursive --new-file v2.1.50/linux/fs/open.c linux/fs/open.c --- v2.1.50/linux/fs/open.c Sun Jul 27 12:11:01 1997 +++ linux/fs/open.c Sat Aug 16 09:55:26 1997 @@ -53,9 +53,6 @@ int error; lock_kernel(); - error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs)); - if (error) - goto out; if (fd >= NR_OPEN || !(file = current->files->fd[fd])) error = -EBADF; else if (!(dentry = file->f_dentry)) @@ -67,8 +64,7 @@ else if (!inode->i_sb->s_op->statfs) error = -ENOSYS; else - inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs)); -out: + error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs)); unlock_kernel(); return error; } diff -u --recursive --new-file v2.1.50/linux/fs/pipe.c linux/fs/pipe.c --- v2.1.50/linux/fs/pipe.c Mon Aug 4 16:25:39 1997 +++ linux/fs/pipe.c Sun Aug 17 09:53:20 1997 @@ -399,7 +399,7 @@ /* * Mark the inode dirty from the very beginning, * that way it will never be moved to the dirty - * list because "make_inode_dirty()" will think + * list because "mark_inode_dirty()" will think * that it already _is_ on the dirty list. */ inode->i_state = 1 << I_DIRTY; @@ -439,7 +439,7 @@ int error; int i,j; - error = ENFILE; + error = -ENFILE; f1 = get_empty_filp(); if (!f1) goto no_files; @@ -462,7 +462,10 @@ goto close_f12_inode_i; j = error; + error = -ENOMEM; f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode, NULL)); + if (!f1->f_dentry) + goto close_f12_inode_i_j; /* read file */ f1->f_pos = f2->f_pos = 0; @@ -480,6 +483,8 @@ fd[1] = j; return 0; +close_f12_inode_i_j: + put_unused_fd(j); close_f12_inode_i: put_unused_fd(i); close_f12_inode: diff -u --recursive --new-file v2.1.50/linux/fs/proc/Makefile linux/fs/proc/Makefile --- v2.1.50/linux/fs/proc/Makefile Thu Jul 17 10:06:07 1997 +++ linux/fs/proc/Makefile Sat Aug 16 09:53:08 1997 @@ -24,4 +24,8 @@ endif endif +ifeq ($(CONFIG_PROC_DEVICETREE),y) +O_OBJS += proc_devtree.o +endif + include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.50/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- v2.1.50/linux/fs/proc/openpromfs.c Mon Aug 4 16:25:39 1997 +++ linux/fs/proc/openpromfs.c Sat Aug 16 10:00:33 1997 @@ -1,4 +1,4 @@ -/* $Id: openpromfs.c,v 1.20 1997/07/22 06:40:07 davem Exp $ +/* $Id: openpromfs.c,v 1.18 1997/07/17 02:24:01 davem Exp $ * openpromfs.c: /proc/openprom handling routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.50/linux/fs/proc/proc_devtree.c linux/fs/proc/proc_devtree.c --- v2.1.50/linux/fs/proc/proc_devtree.c Wed Dec 31 16:00:00 1969 +++ linux/fs/proc/proc_devtree.c Sat Aug 16 09:53:08 1997 @@ -0,0 +1,219 @@ +/* + * proc_devtree.c - handles /proc/device-tree + * + * Copyright 1997 Paul Mackerras + */ +#include +#include +#include +#include +#include +#include +#include + +static struct proc_dir_entry *proc_device_tree; + +/* + * Supply data on a read from /proc/device-tree/node/property. + */ +static int property_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct property *pp = data; + int n; + + if (off >= pp->length) { + *eof = 1; + return 0; + } + n = pp->length - off; + if (n > count) + n = count; + else + *eof = 1; + memcpy(page, pp->value + off, n); + *start = page; + return n; +} + +/* + * For a node with a name like "gc@10", we make symlinks called "gc" + * and "@10" to it. + */ + +static int devtree_readlink(struct inode *, char *, int); +static struct dentry *devtree_follow_link(struct inode *, struct dentry *); + +struct inode_operations devtree_symlink_inode_operations = { + NULL, /* no file-operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + devtree_readlink, /* readlink */ + devtree_follow_link, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; + +static struct dentry *devtree_follow_link(struct inode *inode, + struct dentry *base) +{ + struct proc_dir_entry * de; + char *link; + + de = (struct proc_dir_entry *) inode->u.generic_ip; + link = (char *) de->data; + return lookup_dentry(link, base, 1); +} + +static int devtree_readlink(struct inode *inode, char *buffer, int buflen) +{ + struct proc_dir_entry * de; + char *link; + int linklen; + + de = (struct proc_dir_entry *) inode->u.generic_ip; + link = (char *) de->data; + linklen = strlen(link); + if (linklen > buflen) + linklen = buflen; + if (copy_to_user(buffer, link, linklen)) + return -EFAULT; + return linklen; +} + +/* + * Process a node, adding entries for its children and its properties. + */ +static void add_node(struct device_node *np, struct proc_dir_entry *de) +{ + struct property *pp; + struct proc_dir_entry *ent; + struct device_node *child, *sib; + const char *p, *at; + int l; + struct proc_dir_entry *list, **lastp, *al; + + lastp = &list; + for (pp = np->properties; pp != 0; pp = pp->next) { + /* + * Unfortunately proc_register puts each new entry + * at the beginning of the list. So we rearrange them. + */ + ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (ent == 0) + break; + memset(ent, 0, sizeof(struct proc_dir_entry)); + ent->name = pp->name; + ent->namelen = strlen(pp->name); + ent->mode = S_IFREG | S_IRUGO; + ent->nlink = 1; + ent->data = pp; + ent->read_proc = property_read_proc; + ent->size = pp->length; + proc_register(de, ent); + *lastp = ent; + lastp = &ent->next; + } + for (child = np->child; child != 0; child = child->sibling) { + p = strrchr(child->full_name, '/'); + if (p == 0) + p = child->full_name; + else + ++p; + /* chop off '@0' if the name ends with that */ + l = strlen(p); + if (l > 2 && p[l-2] == '@' && p[l-1] == '0') + l -= 2; + ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (ent == 0) + break; + memset(ent, 0, sizeof(struct proc_dir_entry)); + ent->name = p; + ent->namelen = l; + ent->mode = S_IFDIR | S_IRUGO | S_IXUGO; + ent->nlink = 2; + proc_register(de, ent); + *lastp = ent; + lastp = &ent->next; + add_node(child, ent); + + /* + * If we left the address part on the name, consider + * adding symlinks from the name and address parts. + */ + if (p[l] != 0 || (at = strchr(p, '@')) == 0) + continue; + + /* + * If this is the first node with a given name property, + * add a symlink with the name property as its name. + */ + for (sib = np->child; sib != child; sib = sib->sibling) + if (strcmp(sib->name, child->name) == 0) + break; + if (sib == child && strncmp(p, child->name, l) != 0) { + al = kmalloc(sizeof(struct proc_dir_entry), + GFP_KERNEL); + if (al == 0) + break; + memset(al, 0, sizeof(struct proc_dir_entry)); + al->name = child->name; + al->namelen = strlen(child->name); + al->mode = S_IFLNK | S_IRUGO | S_IXUGO; + al->nlink = 1; + al->data = (void *) ent->name; + al->ops = &devtree_symlink_inode_operations; + proc_register(de, al); + *lastp = al; + lastp = &al->next; + } + + /* + * Add another directory with the @address part as its name. + */ + al = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL); + if (al == 0) + break; + memset(al, 0, sizeof(struct proc_dir_entry)); + al->name = at; + al->namelen = strlen(at); + al->mode = S_IFLNK | S_IRUGO | S_IXUGO; + al->nlink = 1; + al->data = (void *) ent->name; + al->ops = &devtree_symlink_inode_operations; + proc_register(de, al); + *lastp = al; + lastp = &al->next; + } + *lastp = 0; + de->subdir = list; +} + +/* + * Called on initialization to set up the /proc/device-tree subtree + */ +void proc_device_tree_init(void) +{ + struct device_node *root; + + proc_device_tree = create_proc_entry("device-tree", S_IFDIR, 0); + if (proc_device_tree == 0) + return; + root = find_path_device("/"); + if (root == 0) { + printk(KERN_ERR "/proc/device-tree: can't find root\n"); + return; + } + add_node(root, proc_device_tree); +} diff -u --recursive --new-file v2.1.50/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.50/linux/fs/proc/root.c Mon Aug 4 16:25:39 1997 +++ linux/fs/proc/root.c Sat Aug 16 09:53:08 1997 @@ -548,6 +548,13 @@ 0, &proc_omirr_inode_operations }; #endif +#ifdef __powerpc__ +static struct proc_dir_entry proc_root_ppc_htab = { + PROC_PPC_HTAB, 8, "ppc_htab", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_ppc_htab_inode_operations +}; +#endif void proc_root_init(void) { @@ -619,6 +626,12 @@ } proc_tty_init(); +#ifdef __powerpc__ + proc_register(&proc_root, &proc_root_ppc_htab); +#endif +#ifdef CONFIG_PROC_DEVICETREE + proc_device_tree_init(); +#endif } /* diff -u --recursive --new-file v2.1.50/linux/fs/read_write.c linux/fs/read_write.c --- v2.1.50/linux/fs/read_write.c Thu Jul 17 10:06:07 1997 +++ linux/fs/read_write.c Sun Aug 17 10:03:31 1997 @@ -130,7 +130,7 @@ goto bad_file; dentry = file->f_dentry; if (!dentry) - goto bad_file; + goto out; inode = dentry->d_inode; if (!inode) goto out; diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v2.1.50/linux/fs/smbfs/file.c Mon Jun 16 16:35:59 1997 +++ linux/fs/smbfs/file.c Fri Aug 15 12:51:03 1997 @@ -126,8 +126,8 @@ if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; - + mark_inode_dirty(inode); + DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name); return already_read; @@ -196,8 +196,8 @@ } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_dirt = 1; - + mark_inode_dirty(inode); + file->f_pos = pos; if (pos > inode->i_size) diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.1.50/linux/fs/smbfs/inode.c Thu Jun 26 12:33:39 1997 +++ linux/fs/smbfs/inode.c Fri Aug 15 12:51:03 1997 @@ -228,7 +228,7 @@ sb->s_dev = 0; return NULL; } - if (!S_ISSOCK(filp->f_inode->i_mode)) + if (!S_ISSOCK(filp->f_dentry->d_inode->i_mode)) { printk("smb_read_super: not a socket!\n"); sb->s_dev = 0; @@ -305,7 +305,8 @@ } smb_init_root_dirent(server, &(server->root.finfo)); - if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root))))) + if (!(sb->s_root = d_alloc_root(iget(sb, + smb_info_ino(&(server->root))),NULL))) { sb->s_dev = 0; printk("smb_read_super: get root inode failed\n"); diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/mmap.c linux/fs/smbfs/mmap.c --- v2.1.50/linux/fs/smbfs/mmap.c Thu Jul 17 10:06:07 1997 +++ linux/fs/smbfs/mmap.c Fri Aug 15 12:51:03 1997 @@ -27,7 +27,7 @@ smb_file_mmap_nopage(struct vm_area_struct *area, unsigned long address, int no_share) { - struct inode *inode = area->vm_inode; + struct inode *inode = area->vm_dentry->d_inode; unsigned long page; unsigned int clear; unsigned long tmp; @@ -117,7 +117,7 @@ if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; - inode->i_dirt = 1; + mark_inode_dirty(inode); } vma->vm_dentry = dget(file->f_dentry); diff -u --recursive --new-file v2.1.50/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c --- v2.1.50/linux/fs/smbfs/sock.c Mon Apr 7 11:35:31 1997 +++ linux/fs/smbfs/sock.c Fri Aug 15 12:51:03 1997 @@ -128,7 +128,7 @@ if ((server == NULL) || ((file = server->sock_file) == NULL) - || ((inode = file->f_inode) == NULL) + || ((inode = file->f_dentry->d_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { printk("smb_catch_keepalive: did not get valid server!\n"); @@ -175,7 +175,7 @@ if ((server == NULL) || ((file = server->sock_file) == NULL) - || ((inode = file->f_inode) == NULL) + || ((inode = file->f_dentry->d_inode) == NULL) || (!S_ISSOCK(inode->i_mode))) { printk("smb_dont_catch_keepalive: " @@ -322,7 +322,7 @@ return NULL; if ((file = server->sock_file) == NULL) return NULL; - if ((inode = file->f_inode) == NULL) + if ((inode = file->f_dentry->d_inode) == NULL) return NULL; return &(inode->u.socket_i); } diff -u --recursive --new-file v2.1.50/linux/fs/super.c linux/fs/super.c --- v2.1.50/linux/fs/super.c Thu Aug 14 20:49:17 1997 +++ linux/fs/super.c Mon Aug 18 13:04:41 1997 @@ -811,14 +811,12 @@ if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) if (!fs_may_remount_ro(sb)) return -EBUSY; - sb->s_flags = (flags & ~MS_RDONLY) | (sb->s_flags & MS_RDONLY); if (sb->s_op && sb->s_op->remount_fs) { retval = sb->s_op->remount_fs(sb, &flags, data); if (retval) return retval; } - sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | - (flags & MS_RMT_MASK); + sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); vfsmnt = lookup_vfsmnt(sb->s_dev); if (vfsmnt) vfsmnt->mnt_flags = sb->s_flags; diff -u --recursive --new-file v2.1.50/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h --- v2.1.50/linux/include/asm-m68k/pgtable.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-m68k/pgtable.h Sat Aug 16 09:51:09 1997 @@ -159,6 +159,8 @@ } } +#define flush_icache_range(start, end) do { } while (0) + /* * flush all user-space atc entries. */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h --- v2.1.50/linux/include/asm-mips/bitops.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/bitops.h Sat Aug 16 09:51:09 1997 @@ -531,14 +531,16 @@ #define ext2_find_next_zero_bit(addr, size, offset) \ find_next_zero_bit((addr), (size), (offset)) +#endif /* !(__MIPSEB__) */ + /* * Bitmap functions for the minix filesystem. * FIXME: These assume that Minix uses the native byte/bitorder. + * This limits the Minix filesystem's value for data exchange very much. */ #define minix_set_bit(nr,addr) test_and_set_bit(nr,addr) #define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr) #define minix_test_bit(nr,addr) test_bit(nr,addr) #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) -#endif /* __KERNEL__ */ #endif /* __ASM_MIPS_BITOPS_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h --- v2.1.50/linux/include/asm-mips/checksum.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-mips/checksum.h Sat Aug 16 09:51:09 1997 @@ -5,7 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997 by Ralf Baechle + * + * $Id: checksum.h,v 1.5 1997/08/08 20:22:28 miguel Exp $ */ #ifndef __ASM_MIPS_CHECKSUM_H #define __ASM_MIPS_CHECKSUM_H diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h --- v2.1.50/linux/include/asm-mips/floppy.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/floppy.h Sat Aug 16 09:51:09 1997 @@ -71,7 +71,7 @@ { #ifdef CONFIG_MIPS_JAZZ if (mips_machgroup == MACH_GROUP_JAZZ) - vdma_free(PHYSADDR(addr)); + vdma_free(vdma_phys2log(PHYSADDR(addr))); #endif free_pages(addr, __get_order(size)); } diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/gfx.h linux/include/asm-mips/gfx.h --- v2.1.50/linux/include/asm-mips/gfx.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/gfx.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,46 @@ +/* + * This is the user-visible SGI GFX interface. + * + * This must be used verbatim into the GNU libc. It does not include + * any kernel-only bits on it. + * + * miguel@nuclecu.unam.mx + */ + +/* The iocls, yes, they do not make sense, but such is life */ +#define GFX_BASE 100 +#define GFX_GETNUM_BOARDS (GFX_BASE + 1) +#define GFX_GETBOARD_INFO (GFX_BASE + 2) +#define GFX_ATTACH_BOARD (GFX_BASE + 3) +#define GFX_DETACH_BOARD (GFX_BASE + 4) +#define GFX_IS_MANAGED (GFX_BASE + 5) + +#define GFX_MAPALL (GFX_BASE + 10) + +#define GFX_INFO_NAME_SIZE 16 +#define GFX_INFO_LABEL_SIZE 16 + +struct gfx_info { + char name [GFX_INFO_NAME_SIZE]; /* board name */ + char label [GFX_INFO_LABEL_SIZE]; /* label name */ + unsigned short int xpmax, ypmax; /* screen resolution */ + unsigned int lenght; /* size of a complete gfx_info for this board */ +}; + +struct gfx_getboardinfo_args { + unsigned int board; /* board number. starting from zero */ + void *buf; /* pointer to gfx_info */ + unsigned int len; /* buffer size of buf */ +}; + +struct gfx_attach_board_args { + unsigned int board; /* board number, starting from zero */ + void *vaddr; /* address where the board registers should be mapped */ +}; + +#ifdef __KERNEL__ +/* umap.c */ +extern void remove_mapping (struct task_struct *, unsigned long, unsigned long); +extern void *vmalloc_uncached (unsigned long size); +extern int vmap_page_range (unsigned long from, unsigned long size, unsigned long vaddr); +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h --- v2.1.50/linux/include/asm-mips/jazzdma.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-mips/jazzdma.h Sat Aug 16 09:51:09 1997 @@ -21,6 +21,7 @@ void vdma_set_addr(int channel, long addr); void vdma_set_count(int channel, int count); int vdma_get_residue(int channel); +int vdma_get_enable(int channel); /* * some definitions used by the driver functions diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h --- v2.1.50/linux/include/asm-mips/keyboard.h Thu Jun 26 12:33:39 1997 +++ linux/include/asm-mips/keyboard.h Sat Aug 16 09:51:09 1997 @@ -5,9 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * This file is a mess. Put on your peril sensitive glasses. - * - * $Id: keyboard.h,v 1.4 1997/06/16 00:31:46 ralf Exp $ + * $Id: keyboard.h,v 1.5 1997/08/08 20:22:31 miguel Exp $ */ #ifndef __ASM_MIPS_KEYBOARD_H #define __ASM_MIPS_KEYBOARD_H @@ -17,6 +15,7 @@ #include #include #include +#include extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); @@ -26,6 +25,7 @@ extern char pckbd_unexpected_up(unsigned char keycode); extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); +extern unsigned char pckbd_sysrq_xlate[128]; #define kbd_setkeycode pckbd_setkeycode #define kbd_getkeycode pckbd_getkeycode @@ -34,204 +34,76 @@ #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds #define kbd_init_hw pckbd_init_hw +#define kbd_sysrq_xlate pckbd_sysrq_xlate -/* - * The default IO slowdown is doing 'inb()'s from 0x61, which should be - * safe. But as that is the keyboard controller chip address, we do our - * slowdowns here by doing short jumps: the keyboard controller should - * be able to keep up - */ -#define REALLY_SLOW_IO -#define SLOW_IO_BY_JUMPING -#include - -/* - * keyboard controller registers - */ -#define KBD_STATUS_REG (unsigned int) 0x64 -#define KBD_CNTL_REG (unsigned int) 0x64 -#define KBD_DATA_REG (unsigned int) 0x60 +#define SYSRQ_KEY 0x54 -#ifdef CONFIG_SGI -#include -#include -#endif -#include -#include - -#ifdef CONFIG_SGI -#define KEYBOARD_IRQ 20 -#else -/* Not true for Jazz machines, we cheat a bit for 'em. */ -#define KEYBOARD_IRQ 1 -#endif +#define INIT_KBD /* full initialization for the keyboard controller. */ -#ifdef CONFIG_SGI -#define DISABLE_KBD_DURING_INTERRUPTS 1 -#else -#define DISABLE_KBD_DURING_INTERRUPTS 0 -#endif +/* Some stoneage hardware needs delays after some operations. */ +#define kbd_pause() do { } while(0) -#ifndef CONFIG_SGI -#define KBD_REPORT_ERR -#endif -#define KBD_REPORT_UNKN -/* #define KBD_IS_FOCUS_9000 */ +/* Pointers to keyboard hardware access and init functions. */ +unsigned char (*kbd_read_input)(void); +void (*kbd_write_output)(unsigned char val); +void (*kbd_write_command)(unsigned char val); +unsigned char (*kbd_read_status)(void); -int (*kbd_inb_p)(unsigned short port); -int (*kbd_inb)(unsigned short port); -void (*kbd_outb_p)(unsigned char data, unsigned short port); -void (*kbd_outb)(unsigned char data, unsigned short port); +void (*keyboard_setup)(void); #ifdef CONFIG_MIPS_JAZZ -#define INIT_KBD /* full initialization for the keyboard controller. */ -static volatile keyboard_hardware *jazz_kh; +/* Not true for Jazz machines, we cheat a bit for 'em. */ +#define KEYBOARD_IRQ 1 + +/* + * No PS/2 style mouse support for Jazz machines + */ -static int -jazz_kbd_inb_p(unsigned short port) -{ - int result; - - if(port == KBD_DATA_REG) - result = jazz_kh->data; - else /* Must be KBD_STATUS_REG */ - result = jazz_kh->command; - inb(0x80); - - return result; -} - -static int -jazz_kbd_inb(unsigned short port) -{ - int result; - - if(port == KBD_DATA_REG) - result = jazz_kh->data; - else /* Must be KBD_STATUS_REG */ - result = jazz_kh->command; - - return result; -} - -static void -jazz_kbd_outb_p(unsigned char data, unsigned short port) -{ - if(port == KBD_DATA_REG) - jazz_kh->data = data; - else if(port == KBD_CNTL_REG) - jazz_kh->command = data; - inb(0x80); -} - -static void -jazz_kbd_outb(unsigned char data, unsigned short port) -{ - if(port == KBD_DATA_REG) - jazz_kh->data = data; - else if(port == KBD_CNTL_REG) - jazz_kh->command = data; -} #endif /* CONFIG_MIPS_JAZZ */ #ifdef CONFIG_SGI -#define INIT_KBD /* full initialization for the keyboard controller. */ -static volatile struct hpc_keyb *sgi_kh; +#define DISABLE_KBD_DURING_INTERRUPTS 1 + +#define KEYBOARD_IRQ 20 + +/* + * Machine specific bits for the PS/2 driver. + * Aux device and keyboard share the interrupt on the Indy. + */ + +#define ps2_request_irq() 0 +#define ps2_free_irq(void) do { } while(0); -static int -sgi_kbd_inb(unsigned short port) -{ - int result; - - if(port == KBD_DATA_REG) - result = sgi_kh->data; - else /* Must be KBD_STATUS_REG */ - result = sgi_kh->command; - - return result; -} - -static void -sgi_kbd_outb(unsigned char data, unsigned short port) -{ - if(port == KBD_DATA_REG) - sgi_kh->data = data; - else if(port == KBD_CNTL_REG) - sgi_kh->command = data; -} #endif /* CONFIG_SGI */ +#if defined(CONFIG_ACER_PICA_61) || defined(CONFIG_SNI_RM200_PCI) \ + || defined(CONFIG_DESKSTATION_RPC44) || defined(CONFIG_DESKSTATION_TYNE) +#define CONF_KEYBOARD_USES_IO_PORTS +#endif + +#ifdef CONF_KEYBOARD_USES_IO_PORTS /* * Most other MIPS machines access the keyboard controller via - * ordinary I/O ports. + * memory mapped I/O ports. */ -static int -port_kbd_inb_p(unsigned short port) -{ - return inb_p(port); -} - -static int -port_kbd_inb(unsigned short port) -{ - return inb(port); -} - -static void -port_kbd_outb_p(unsigned char data, unsigned short port) -{ - return outb_p(data, port); -} - -static void -port_kbd_outb(unsigned char data, unsigned short port) -{ - return outb(data, port); -} +#include -extern __inline__ void keyboard_setup(void) -{ -#ifdef CONFIG_MIPS_JAZZ - if (mips_machgroup == MACH_GROUP_JAZZ) { - jazz_kh = (void *) JAZZ_KEYBOARD_ADDRESS; - kbd_inb_p = jazz_kbd_inb_p; - kbd_inb = jazz_kbd_inb; - kbd_outb_p = jazz_kbd_outb_p; - kbd_outb = jazz_kbd_outb; - /* - * Enable keyboard interrupts. - */ - *((volatile u16 *)JAZZ_IO_IRQ_ENABLE) |= JAZZ_IE_KEYBOARD; - set_cp0_status(IE_IRQ1, IE_IRQ1); - } else -#endif - if (mips_machgroup == MACH_GROUP_ARC || /* this is for Deskstation */ - (mips_machgroup == MACH_GROUP_SNI_RM - && mips_machtype == MACH_SNI_RM200_PCI)) { - /* - * These machines address their keyboard via the normal - * port address range. - * - * Also enable Scan Mode 2. - */ - kbd_inb_p = port_kbd_inb_p; - kbd_inb = port_kbd_inb; - kbd_outb_p = port_kbd_outb_p; - kbd_outb = port_kbd_outb; - request_region(0x60,16,"keyboard"); - } -#ifdef CONFIG_SGI - if (mips_machgroup == MACH_GROUP_SGI) { - sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); - kbd_inb_p = sgi_kbd_inb; - kbd_inb = sgi_kbd_inb; - kbd_outb_p = sgi_kbd_outb; - kbd_outb = sgi_kbd_outb; - } -#endif -} +#define KEYBOARD_IRQ 1 + +/* + * Machine specific bits for the PS/2 driver + */ + +#define AUX_IRQ 12 + +#define ps2_request_irq() \ + request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL) + +#define ps2_free_irq(inode) free_irq(AUX_IRQ, NULL) + +#endif /* CONF_KEYBOARD_USES_IO_PORTS */ #endif /* __KERNEL */ #endif /* __ASM_MIPS_KEYBOARD_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/ng1.h linux/include/asm-mips/ng1.h --- v2.1.50/linux/include/asm-mips/ng1.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/ng1.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,26 @@ +/* + * SGI/Newport video card ioctl definitions + * + */ + +typedef struct { + int flags; + u16 w, h; + u16 fields_sec; +} ng1_vof_info_t; + +struct ng1_info { + struct gfx_info gfx_info; + u8 boardrev; + u8 rex3rev; + u8 vc2rev; + u8 monitortype; + u8 videoinstalled; + u8 mcrev; + u8 bitplanes; + u8 xmap9rev; + u8 cmaprev; + ng1_vof_info_t ng1_vof_info; + u8 bt445rev; + u8 paneltype; +}; diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h --- v2.1.50/linux/include/asm-mips/pgtable.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-mips/pgtable.h Sat Aug 16 09:51:09 1997 @@ -16,6 +16,7 @@ * - flush_cache_page(mm, vmaddr) flushes a single page * - flush_cache_range(mm, start, end) flushes a range of pages * - flush_page_to_ram(page) write back kernel page to ram + * */ extern void (*flush_cache_all)(void); extern void (*flush_cache_mm)(struct mm_struct *mm); @@ -24,6 +25,7 @@ extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); extern void (*flush_cache_sigtramp)(unsigned long addr); extern void (*flush_page_to_ram)(unsigned long page); +#define flush_icache_range(start, end) do { } while (0) /* TLB flushing: * @@ -38,6 +40,13 @@ unsigned long end); extern void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); +/* + * - add_wired_entry() add a fixed TLB entry, and move wired register + */ +extern void (*add_wired_entry)(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask); + + /* Basically we have the same two-level (which is the logical three level * Linux page table layout folded) page tables as the i386. Some day * when we have proper page coloring support we can have a 1% quicker @@ -108,21 +117,25 @@ #define _CACHE_CACHABLE_ACCELERATED (7<<9) /* R10000 only */ #define _CACHE_MASK (7<<9) -#define __READABLE (_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED) -#define __WRITEABLE (_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED) +#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED) +#define __WRITEABLE (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED) #define _PAGE_CHG_MASK (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK) #define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ - _PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT) + _CACHE_CACHABLE_NONCOHERENT) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | \ _CACHE_CACHABLE_NONCOHERENT) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _CACHE_CACHABLE_NONCOHERENT) +#define PAGE_USERIO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _CACHE_UNCACHED) +#define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ + _CACHE_UNCACHED) /* * MIPS can't do page protection for execute, and considers that the same like @@ -217,7 +230,7 @@ */ extern inline void set_pte(pte_t *ptep, pte_t pteval) { - *ptep = pteval; + *ptep = pteval; } extern inline void pte_clear(pte_t *ptep) @@ -230,7 +243,7 @@ */ extern inline int pmd_none(pmd_t pmd) { - return pmd_val(pmd) == ((unsigned long) invalid_pte_table); + return pmd_val(pmd) == (unsigned long) invalid_pte_table; } extern inline int pmd_bad(pmd_t pmd) @@ -288,7 +301,7 @@ extern inline pte_t pte_mkold(pte_t pte) { - pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); + pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); return pte; } @@ -319,12 +332,8 @@ extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; - if (pte_val(pte) & _PAGE_READ) { + if (pte_val(pte) & _PAGE_READ) pte_val(pte) |= _PAGE_SILENT_READ; - if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == - (_PAGE_WRITE|_PAGE_MODIFIED)) - pte_val(pte) |= _PAGE_SILENT_WRITE; - } return pte; } @@ -541,7 +550,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $5\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -553,7 +562,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $5\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -567,7 +576,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $2\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -579,7 +588,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $2\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -592,7 +601,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $3\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -604,7 +613,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $3\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -618,7 +627,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $10\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); @@ -631,7 +640,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $10\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -645,7 +654,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $0\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -657,7 +666,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $0\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder\n\t" : : "r" (val)); } @@ -671,7 +680,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $6\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder\n\t" : "=r" (val)); return val; @@ -683,7 +692,7 @@ "\n\t.set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $6\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -697,7 +706,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $28\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -709,7 +718,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $28\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -722,7 +731,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $29\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); return val; @@ -734,7 +743,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $29\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } @@ -748,7 +757,7 @@ ".set noreorder\n\t" ".set mips3\n\t" "mfc0 %0, $4\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : "=r" (val)); @@ -761,14 +770,11 @@ ".set noreorder\n\t" ".set mips3\n\t" "mtc0 %0, $4\n\t" - ".set mips2\n\t" + ".set mips0\n\t" ".set reorder" : : "r" (val)); } #endif /* !defined (__LANGUAGE_ASSEMBLY__) */ - -#define module_map vmalloc -#define module_unmap vfree #endif /* __ASM_MIPS_PGTABLE_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/rrm.h linux/include/asm-mips/rrm.h --- v2.1.50/linux/include/asm-mips/rrm.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/rrm.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,88 @@ +/* + * SGI Rendering Resource Manager API (?). + * + * written by Miguel de Icaza (miguel@nuclecu.unam.mx) + * + * Ok, even if SGI choosed to do mmap trough ioctls, their + * kernel support for virtualizing the graphics card is nice. + * + * We should be able to make graphic applications on Linux + * fly. + * + * This header file should be included from GNU libc as well. + */ + + +/* Why like this you say? Well, gdb can print enums */ +#define RRM_BASE 1000 +#define RRM_CMD_LIMIT (RRM_BASE + 100) + +enum { + RRM_OPENRN = RRM_BASE, /* open rendering node */ + RRM_CLOSERN, + RRM_BINDPROCTORN, /* set current rendering region for node */ + RRM_BINDRNTOCLIP, + RRM_UNBINDRNFROMCLIP, + RRM_SWAPBUF, + RRM_SETSWAPINTERVAL, + RRM_WAITFORRETRACE, + RRM_SETDISPLAYMODE, + RRM_MESSAGE, + RRM_INVALIDATERN, + RRM_VALIDATECLIP, + RRM_VALIDATESWAPBUF, + RRM_SWAPGROUP, + RRM_SWAPUNGROUP, + RRM_VALIDATEMESSAGE, + RRM_GETDISPLAYMODES, + RRM_LOADDISPLAYMODE, + RRM_CUSHIONBUFFER, + RRM_SWAPREADY, + RRM_MGR_SWAPBUF, + RRM_SETVSYNC, + RRM_GETVSYNC, + RRM_WAITVSYNC, + RRM_BINDRNTOREADANDCLIP, + RRM_MAPCLIPTOSWPBUFID +}; + +/* Parameters for the above ioctls + * + * All of the ioctls take as their first argument the rendering node id. + * + */ + +/* + * RRM_OPENRN: + * + * This is called by the IRIX X server with: + * rnid = 0xffffffff rmask = 0 + * + * Returns a number like this: 0x10001. + * If you run the X server over and over, you get a value + * that is of the form (n * 0x10000) + 1. + * + * The return value seems to be the RNID. + */ +struct RRM_OpenRN { + int rnid; + unsigned int rmask; +}; + +struct RRM_CloseRN { + int rnid; +}; + +/* + * RRM_BINDPROCTORN: + * + * Return value when the X server calls it: 0 + */ +struct RRM_BindProcToRN { + int rnid; +}; + +#ifdef __KERNEL__ +int rrm_command (unsigned int cmd, void *arg); +int rrm_close (struct inode *inode, struct file *file); +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/shmiq.h linux/include/asm-mips/shmiq.h --- v2.1.50/linux/include/asm-mips/shmiq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-mips/shmiq.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,195 @@ +/* + * Please note that the comments on this file may be out of date + * and that they represent what I have figured about the shmiq device + * so far in IRIX. + * + * This also contains some streams and idev bits. + * + * They may contain errors, please, refer to the source code of the Linux + * kernel for a definitive answer on what we have implemented + * + * Miguel. + */ + +/* STREAMs ioctls */ +#define STRIOC ('S' << 8) +#define I_STR (STRIOC | 010) +#define I_PUSH (STRIOC | 02) +#define I_LINK (STRIOC | 014) +#define I_UNLINK (STRIOC | 015) + +/* Data structure passed on I_STR ioctls */ +struct strioctl { + int ic_cmd; /* streams ioctl command */ + int ic_timout; /* timeout */ + int ic_len; /* lenght of data */ + void *ic_dp; /* data */ +}; + +/* + * For mapping the shared memory input queue, you have to: + * + * 1. Map /dev/zero for the number of bytes you want to use + * for your shared memory input queue plus the size of the + * sharedMemoryInputQueue structure + 4 (I still have not figured + * what this one is for + * + * 2. Open /dev/shmiq + * + * 3. Open /dev/qcntlN N is [0..Nshmiqs] + * + * 4. Fill a shmiqreq structure. user_vaddr should point to the return + * address from the /dev/zero mmap. Arg is the number of shmqevents + * that fit into the /dev/zero region (remember that at the beginning there + * is a sharedMemoryInputQueue header). + * + * 5. Issue the ioctl (qcntlfd, QIOCATTACH, &your_shmiqreq); + */ + +struct shmiqreq { + char *user_vaddr; + int arg; +}; + +/* map the shmiq into the process address space */ +#define QIOCATTACH _IOW('Q',1,struct shmiqreq) + +/* remove mappings */ +#define QIOCDETACH _IO('Q',2) + +/* + * A shared memory input queue event. + */ +struct shmqdata { + unsigned char device; /* device major */ + unsigned char which; /* device minor */ + unsigned char type; /* event type */ + unsigned char flags; /* little event data */ + union { + int pos; /* big event data */ + short ptraxis [2]; /* event data for PTR events */ + } un; +}; + +/* indetifies the shmiq and the device */ +struct shmiqlinkid { + short int devminor; + short int index; +}; + +struct shmqevent { + union { + int time; + struct shmiqlinkid id; + } un ; + struct shmqdata data ; +}; + +/* + * sharedMemoryInputQueue: this describes the shared memory input queue. + * + * head is the user index into the events, user can modify this one. + * tail is managed by the kernel. + * flags is one of SHMIQ_OVERFLOW or SHMIQ_CORRUPTED + * if OVERFLOW is set it seems ioctl QUIOCSERVICED should be called + * to notify the kernel. + * events where the kernel sticks the events. + */ +struct sharedMemoryInputQueue { + volatile int head; /* user's index into events */ + volatile int tail; /* kernel's index into events */ + volatile unsigned int flags; /* place for out-of-band data */ +#define SHMIQ_OVERFLOW 1 +#define SHMIQ_CORRUPTED 2 + struct shmqevent events[1]; /* input event buffer */ +}; + +/* have to figure this one out */ +#define QIOCGETINDX _IOWR('Q', 8, int) + + +/* acknowledge shmiq overflow */ +#define QIOCSERVICED _IO('Q', 3) + +/* Double indirect I_STR ioctl, yeah, fun fun fun */ + +struct muxioctl { + int index; /* lower stream index */ + int realcmd; /* the actual command for the subdevice */ +}; +/* Double indirect ioctl */ +#define QIOCIISTR _IOW('Q', 7, struct muxioctl) + +/* Cursor ioclts: */ + +/* set cursor tracking mode */ +#define QIOCURSTRK _IOW('Q', 4, int) + +/* set cursor filter box */ +#define QIOCURSIGN _IOW('Q', 5, int [4]) + +/* set cursor axes */ +struct shmiqsetcurs { + short index; + short axes; +}; + +#define QIOCSETCURS _IOWR('Q', 9, struct shmiqsetcurs) + +/* set cursor position */ +struct shmiqsetcpos { + short x; + short y; +}; +#define QIOCSETCPOS _IOWR('Q', 10, struct shmiqsetcpos) + +/* get time since last event */ +#define QIOCGETITIME _IOR('Q', 11, time_t) + +/* set curent screen */ +#define QIOCSETSCRN _IOW('Q',6,int) + + +/* -------------------- iDev stuff -------------------- */ + +#define IDEV_MAX_NAME_LEN 15 +#define IDEV_MAX_TYPE_LEN 15 + +typedef struct { + char devName[IDEV_MAX_NAME_LEN+1]; + char devType[IDEV_MAX_TYPE_LEN+1]; + unsigned short nButtons; + unsigned short nValuators; + unsigned short nLEDs; + unsigned short nStrDpys; + unsigned short nIntDpys; + unsigned char nBells; + unsigned char flags; +#define IDEV_HAS_KEYMAP 0x01 +#define IDEV_HAS_PROXIMITY 0x02 +#define IDEV_HAS_PCKBD 0x04 +} idevDesc; + +typedef struct { + char *nothing_for_now; +} idevInfo; + +typedef struct { + char name [16]; +} idevKeymapDesc; + +#define IDEVINITDEVICE _IOW('i', 51, unsigned int) +#define IDEVGETDEVICEDESC _IOWR('i', 0, idevDesc) +#define IDEVGETKEYMAPDESC _IOWR('i', 2, idevKeymapDesc) + +#ifdef __KERNEL__ + +/* These are only interpreted by SHMIQ-attacheable devices and are internal + * to the kernel + */ +#define SHMIQ_OFF _IO('Q',1) +#define SHMIQ_ON _IO('Q',2) + +void shmiq_push_event (struct shmqevent *e); +int get_sioc (struct strioctl *sioc, unsigned long arg); +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/string.h linux/include/asm-mips/string.h --- v2.1.50/linux/include/asm-mips/string.h Thu Jun 26 12:33:40 1997 +++ linux/include/asm-mips/string.h Sat Aug 16 09:51:09 1997 @@ -5,7 +5,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1994, 1995, 1996 by Ralf Baechle + * Copyright (c) 1994, 1995, 1996, 1997 by Ralf Baechle + * + * $Id: string.h,v 1.4 1997/08/08 20:22:34 miguel Exp $ */ #ifndef __ASM_MIPS_STRING_H #define __ASM_MIPS_STRING_H @@ -117,7 +119,7 @@ } #define __HAVE_ARCH_MEMSET -extern void *memset(void *__s, char __c, size_t __count); +extern void *memset(void *__s, int __c, size_t __count); #define __HAVE_ARCH_MEMCPY extern void *memcpy(void *__to, __const__ void *__from, size_t __n); diff -u --recursive --new-file v2.1.50/linux/include/asm-mips/system.h linux/include/asm-mips/system.h --- v2.1.50/linux/include/asm-mips/system.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-mips/system.h Sat Aug 16 09:51:09 1997 @@ -252,7 +252,7 @@ return x; } -extern unsigned long IRQ_vectors[16]; +extern unsigned long IRQ_vectors[32]; extern unsigned long exception_handlers[32]; #define set_int_vector(n,addr) \ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h --- v2.1.50/linux/include/asm-ppc/bitops.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/bitops.h Sat Aug 16 09:51:09 1997 @@ -1,17 +1,26 @@ +/* + * $Id: bitops.h,v 1.7 1997/08/03 00:12:07 paulus Exp $ + * bitops.h: Bit string operations on the ppc + */ + #ifndef _ASM_PPC_BITOPS_H_ #define _ASM_PPC_BITOPS_H_ #include #include -#include /* for printk */ - -#define BIT(n) 1<<(n&0x1F) -typedef unsigned long BITFIELD; +extern void set_bit(int nr, volatile void *addr); +extern void clear_bit(int nr, volatile void *addr); +extern void change_bit(int nr, volatile void *addr); +extern int test_and_set_bit(int nr, volatile void *addr); +extern int test_and_clear_bit(int nr, volatile void *addr); +extern int test_and_change_bit(int nr, volatile void *addr); /* - * These are ifdef'd out here because using : "cc" as a constraing + * These are if'd out here because using : "cc" as a constraint * results in errors from gcc. -- Cort + * Besides, they need to be changed so we have both set_bit + * and test_and_set_bit, etc. */ #if 0 extern __inline__ int set_bit(int nr, void * addr) @@ -20,9 +29,6 @@ unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk("set_bit(%lx, %p)\n", nr, addr); - __asm__ __volatile__( "1:lwarx %0,0,%3 \n\t" "or %1,%0,%2 \n\t" @@ -32,7 +38,7 @@ : "r" (mask), "r" (p) /*: "cc" */); -n return (old & mask) != 0; + return (old & mask) != 0; } extern __inline__ unsigned long clear_bit(unsigned long nr, void *addr) @@ -41,8 +47,6 @@ unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk("clear_bit(%lx, %p)\n", nr, addr); __asm__ __volatile__("\n\ 1: lwarx %0,0,%3 andc %1,%0,%2 @@ -61,8 +65,6 @@ unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk("change_bit(%lx, %p)\n", nr, addr); __asm__ __volatile__("\n\ 1: lwarx %0,0,%3 xor %1,%0,%2 @@ -76,10 +78,19 @@ } #endif +extern __inline__ unsigned long test_bit(int nr, __const__ volatile void *addr) +{ + __const__ unsigned int *p = (__const__ unsigned int *) addr; + + return (p[nr >> 5] >> (nr & 0x1f)) & 1UL; +} + extern __inline__ int ffz(unsigned int x) { int n; + if (x == ~0) + return 32; x = ~x & (x+1); /* set LS zero to 1, other bits to 0 */ __asm__ ("cntlzw %0,%1" : "=r" (n) : "r" (x)); return 31 - n; @@ -89,34 +100,11 @@ * This implementation of find_{first,next}_zero_bit was stolen from * Linus' asm-alpha/bitops.h. */ +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) -extern __inline__ unsigned long find_first_zero_bit(void * addr, unsigned long size) -{ - unsigned int * p = ((unsigned int *) addr); - unsigned int result = 0; - unsigned int tmp; - - if (size == 0) - return 0; - while (size & ~31UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; - tmp |= ~0UL << size; -found_middle: - return result + ffz(tmp); -} - -/* - * Find next zero bit in a bitmap reasonably efficiently.. - */ -extern __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, - unsigned long offset) +extern __inline__ unsigned long find_next_zero_bit(void * addr, + unsigned long size, unsigned long offset) { unsigned int * p = ((unsigned int *) addr) + (offset >> 5); unsigned int result = offset & ~31UL; @@ -127,17 +115,17 @@ size -= result; offset &= 31UL; if (offset) { - tmp = *(p++); + tmp = *p++; tmp |= ~0UL >> (32-offset); if (size < 32) goto found_first; - if (~tmp) + if (tmp != ~0U) goto found_middle; size -= 32; result += 32; } - while (size & ~31UL) { - if (~(tmp = *(p++))) + while (size >= 32) { + if ((tmp = *p++) != ~0U) goto found_middle; result += 32; size -= 32; @@ -153,101 +141,98 @@ #define _EXT2_HAVE_ASM_BITOPS_ -#define ext2_find_first_zero_bit(addr, size) \ - ext2_find_next_zero_bit((addr), (size), 0) +#ifdef __KERNEL__ +/* + * test_and_{set,clear}_bit guarantee atomicity without + * disabling interrupts. + */ +#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr) +#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr) +#else extern __inline__ int ext2_set_bit(int nr, void * addr) { -#ifdef __KERNEL__ - int s = _disable_interrupts(); -#endif - int mask; - unsigned char *ADDR = (unsigned char *) addr; - int oldbit; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - oldbit = (*ADDR & mask) ? 1 : 0; - *ADDR |= mask; -#ifdef __KERNEL__ - _enable_interrupts(s); -#endif - return oldbit; + int mask; + unsigned char *ADDR = (unsigned char *) addr; + int oldbit; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + oldbit = (*ADDR & mask) ? 1 : 0; + *ADDR |= mask; + return oldbit; } extern __inline__ int ext2_clear_bit(int nr, void * addr) { -#ifdef __KERNEL__ - int s = _disable_interrupts(); -#endif - int mask; - unsigned char *ADDR = (unsigned char *) addr; - int oldbit; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - oldbit = (*ADDR & mask) ? 1 : 0; - *ADDR = *ADDR & ~mask; -#ifdef __KERNEL__ - _enable_interrupts(s); -#endif - return oldbit; -} + int mask; + unsigned char *ADDR = (unsigned char *) addr; + int oldbit; - -/* The following routine need not be atomic. */ -extern __inline__ unsigned long test_bit(int nr, void *addr) -{ - return 1UL & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31)); + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + oldbit = (*ADDR & mask) ? 1 : 0; + *ADDR = *ADDR & ~mask; + return oldbit; } +#endif /* __KERNEL__ */ extern __inline__ int ext2_test_bit(int nr, __const__ void * addr) { - int mask; __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - return ((mask & *ADDR) != 0); + return (ADDR[nr >> 3] >> (nr & 7)) & 1; } -extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset) +/* + * This implementation of ext2_find_{first,next}_zero_bit was stolen from + * Linus' asm-alpha/bitops.h and modified for a big-endian machine. + */ + +#define ext2_find_first_zero_bit(addr, size) \ + ext2_find_next_zero_bit((addr), (size), 0) + +extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, + unsigned long size, unsigned long offset) { - unsigned long *p = ((unsigned long *) addr) + (offset >> 5); - unsigned long result = offset & ~31UL; - unsigned long tmp; + unsigned int *p = ((unsigned int *) addr) + (offset >> 5); + unsigned int result = offset & ~31UL; + unsigned int tmp; if (offset >= size) return size; size -= result; offset &= 31UL; - if(offset) { - tmp = *(p++); - tmp |= le32_to_cpu(~0UL >> (32-offset)); - if(size < 32) + if (offset) { + tmp = cpu_to_le32p(p++); + tmp |= ~0UL >> (32-offset); + if (size < 32) goto found_first; - if(~tmp) + if (tmp != ~0U) goto found_middle; size -= 32; result += 32; } - while(size & ~31UL) { - if(~(tmp = *(p++))) + while (size >= 32) { + if ((tmp = cpu_to_le32p(p++)) != ~0U) goto found_middle; result += 32; size -= 32; } - if(!size) + if (!size) return result; - tmp = *p; - + tmp = cpu_to_le32p(p); found_first: - return result + ffz(le32_to_cpu(tmp) | (~0UL << size)); + tmp |= ~0U << size; found_middle: - return result + ffz(le32_to_cpu(tmp)); + return result + ffz(tmp); } -#endif /* _ASM_PPC_BITOPS_H */ - +/* Bitmap functions for the minix filesystem. */ +#define minix_set_bit(nr,addr) ext2_set_bit(nr,addr) +#define minix_clear_bit(nr,addr) ext2_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size) +#endif /* _ASM_PPC_BITOPS_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h --- v2.1.50/linux/include/asm-ppc/byteorder.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/byteorder.h Sat Aug 16 09:51:09 1997 @@ -4,17 +4,17 @@ #include #ifndef __BIG_ENDIAN -#define __BIG_ENDIAN +#define __BIG_ENDIAN 4321 #endif #ifndef __BIG_ENDIAN_BITFIELD #define __BIG_ENDIAN_BITFIELD #endif -#define ntohl(x) (x) -#define ntohs(x) (x) -#define htonl(x) (x) -#define htons(x) (x) +#define ntohl(x) ((unsigned long)(x)) +#define ntohs(x) ((unsigned short)(x)) +#define htonl(x) ((unsigned long)(x)) +#define htons(x) ((unsigned short)(x)) #define __htonl(x) ntohl(x) #define __htons(x) ntohs(x) @@ -54,7 +54,7 @@ asm volatile("stwbrx %0,0,%1" : : "r" (val), "r" (addr) : "memory"); } - +#if 0 extern __inline__ __u16 cpu_to_le16(__u16 value) { return ld_le16(&value); @@ -63,6 +63,29 @@ { return ld_le32(&value); } +#else +extern __inline__ __u16 cpu_to_le16(__u16 value) +{ + __u16 result; + + asm("rlwimi %0,%1,8,16,23" + : "=r" (result) + : "r" (value), "0" (value >> 8)); + return result; +} +extern __inline__ __u32 cpu_to_le32(__u32 value) +{ + __u32 result; + + asm("rlwimi %0,%1,24,16,23\n\t" + "rlwimi %0,%1,8,8,15\n\t" + "rlwimi %0,%1,24,0,7" + : "=r" (result) + : "r" (value), "0" (value >> 24)); + return result; +} +#endif /* 0 */ + #define cpu_to_be16(x) (x) #define cpu_to_be32(x) (x) diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/checksum.h linux/include/asm-ppc/checksum.h --- v2.1.50/linux/include/asm-ppc/checksum.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/checksum.h Sat Aug 16 09:51:09 1997 @@ -3,22 +3,6 @@ /* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -extern unsigned short int csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum); - -/* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) * @@ -30,43 +14,76 @@ * * it's best to have buff aligned on a 32-bit boundary */ -extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); +extern unsigned int csum_partial(const unsigned char * buff, int len, + unsigned int sum); /* - * the same as csum_partial, but copies from src while it - * checksums + * Computes the checksum of a memory block at src, length len, + * and adds in "sum" (32-bit), while copying the block to dst. + * If an access exception occurs on src or dst, it stores -EFAULT + * to *src_err or *dst_err respectively (if that pointer is not + * NULL), and, for an error on src, zeroes the rest of dst. * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary + * Like csum_partial, this must be called with even lengths, + * except for the last fragment. */ -unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); +extern unsigned int csum_partial_copy_generic(const char *src, char *dst, + int len, unsigned int sum, + int *src_err, int *dst_err); + +#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ + csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0) /* - * the same as csum_partial, but copies from user space (but on the alpha - * we have just one address space, so this is identical to the above) + * Old versions which ignore errors. */ -#define csum_partial_copy_fromuser csum_partial_copy +#define csum_partial_copy(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0) +#define csum_partial_copy_fromuser(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0) + /* - * this is a new version of the above that records errors it finds in *errp, - * but continues and zeros the rest of the buffer. - * - * right now - it just calls csum_partial_copy() - * -- Cort + * turns a 32-bit partial checksum (e.g. from csum_partial) into a + * 1's complement 16-bit checksum. */ -extern __inline__ -unsigned int csum_partial_copy_from_user ( const char *src, char *dst, - int len, int sum, int *err_ptr) +static inline unsigned int csum_fold(unsigned int sum) { - int *dst_err_ptr=NULL; - return csum_partial_copy( src, dst, len, sum); + unsigned int tmp; + + /* swap the two 16-bit halves of sum */ + __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); + /* if there is a carry from adding the two 16-bit halves, + it will carry from the lower half into the upper half, + giving us the correct sum in the upper half. */ + sum = ~(sum + tmp) >> 16; + return sum; } /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c -A */ + */ +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. ihl is the number + * of 32-bit words and is always >= 5. + */ +extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +extern unsigned short csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum); -extern unsigned short ip_compute_csum(unsigned char * buff, int len); -extern unsigned int csum_fold(unsigned int sum); #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/cuda.h linux/include/asm-ppc/cuda.h --- v2.1.50/linux/include/asm-ppc/cuda.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/cuda.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,74 @@ +/* + * Definitions for talking to the CUDA. The CUDA is a microcontroller + * which controls the ADB, system power, RTC, and various other things. + * + * Copyright (C) 1996 Paul Mackerras. + */ + +/* First byte sent to or received from CUDA */ +#define ADB_PACKET 0 +#define CUDA_PACKET 1 +#define ERROR_PACKET 2 +#define TIMER_PACKET 3 +#define POWER_PACKET 4 +#define MACIIC_PACKET 5 + +/* ADB commands (2nd byte) */ +#define ADB_BUSRESET 0 +#define ADB_FLUSH(id) (1 + ((id) << 4)) +#define ADB_WRITEREG(id, reg) (8 + (reg) + ((id) << 4)) +#define ADB_READREG(id, reg) (0xc + (reg) + ((id) << 4)) + +/* ADB default device IDs (upper 4 bits of 2nd byte) */ +#define ADB_DONGLE 1 /* "software execution control" devices */ +#define ADB_KEYBOARD 2 +#define ADB_MOUSE 3 +#define ADB_TABLET 4 +#define ADB_MODEM 5 +#define ADB_MISC 7 /* maybe a monitor */ + +/* CUDA commands (2nd byte) */ +#define CUDA_WARM_START 0 +#define CUDA_AUTOPOLL 1 +#define CUDA_GET_6805_ADDR 2 +#define CUDA_GET_TIME 3 +#define CUDA_GET_PRAM 7 +#define CUDA_SET_6805_ADDR 8 +#define CUDA_SET_TIME 9 +#define CUDA_POWERDOWN 0xa +#define CUDA_POWERUP_TIME 0xb +#define CUDA_SET_PRAM 0xc +#define CUDA_MS_RESET 0xd +#define CUDA_SEND_DFAC 0xe +#define CUDA_RESET_SYSTEM 0x11 +#define CUDA_SET_IPL 0x12 +#define CUDA_SET_AUTO_RATE 0x14 +#define CUDA_GET_AUTO_RATE 0x16 +#define CUDA_SET_DEVICE_LIST 0x19 +#define CUDA_GET_DEVICE_LIST 0x1a +#define CUDA_GET_SET_IIC 0x22 + +#ifdef __KERNEL__ + +struct cuda_request { + unsigned char data[16]; + int nbytes; + unsigned char reply[16]; + int reply_len; + unsigned char reply_expected; + unsigned char sent; + unsigned char got_reply; + void (*done)(struct cuda_request *); + void *arg; + struct cuda_request *next; +}; + +void via_cuda_init(void); +int cuda_request(struct cuda_request *req, + void (*done)(struct cuda_request *), int nbytes, ...); +int cuda_send_request(struct cuda_request *req); +void cuda_poll(void); +int adb_register(int default_id, + void (*handler)(unsigned char *, int, struct pt_regs *)); + +#endif /* __KERNEL */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/current.h linux/include/asm-ppc/current.h --- v2.1.50/linux/include/asm-ppc/current.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/current.h Sat Aug 16 09:51:09 1997 @@ -1,10 +1,9 @@ #ifndef _PPC_CURRENT_H #define _PPC_CURRENT_H -#include - -extern struct task_struct *current_set[1]; - -register struct task_struct *current asm("r2"); +/* + * We keep `current' in r2 for speed. + */ +register struct task_struct *current asm ("r2"); #endif /* !(_PPC_CURRENT_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/dbdma.h linux/include/asm-ppc/dbdma.h --- v2.1.50/linux/include/asm-ppc/dbdma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/dbdma.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,92 @@ +/* + * Definitions for using the Apple Descriptor-Based DMA controller + * in Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + */ + +#ifndef _ASM_DBDMA_H_ +#define _ASM_DBDMA_H_ +/* + * DBDMA control/status registers. All little-endian. + */ +struct dbdma_regs { + unsigned int control; /* lets you change bits in status */ + unsigned int status; /* DMA and device status bits (see below) */ + unsigned int cmdptr_hi; /* upper 32 bits of command address */ + unsigned int cmdptr; /* (lower 32 bits of) command address (phys) */ + unsigned int intr_sel; /* select interrupt condition bit */ + unsigned int br_sel; /* select branch condition bit */ + unsigned int wait_sel; /* select wait condition bit */ + unsigned int xfer_mode; + unsigned int data2ptr_hi; + unsigned int data2ptr; + unsigned int res1; + unsigned int address_hi; + unsigned int br_addr_hi; + unsigned int res2[3]; +}; + +/* Bits in control and status registers */ +#define RUN 0x8000 +#define PAUSE 0x4000 +#define FLUSH 0x2000 +#define WAKE 0x1000 +#define DEAD 0x0800 +#define ACTIVE 0x0400 +#define BT 0x0100 +#define DEVSTAT 0x00ff + +/* + * DBDMA command structure. These fields are all little-endian! + */ +struct dbdma_cmd { + unsigned short req_count; /* requested byte transfer count */ + unsigned short command; /* command word (has bit-fields) */ + unsigned int phy_addr; /* physical data address */ + unsigned int cmd_dep; /* command-dependent field */ + unsigned short res_count; /* residual count after completion */ + unsigned short xfer_status; /* transfer status */ +}; + +/* DBDMA command values in command field */ +#define OUTPUT_MORE 0 /* transfer memory data to stream */ +#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */ +#define INPUT_MORE 0x2000 /* transfer stream data to memory */ +#define INPUT_LAST 0x3000 /* ditto, expect end marker */ +#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */ +#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */ +#define DBDMA_NOP 0x6000 /* do nothing */ +#define DBDMA_STOP 0x7000 /* suspend processing */ + +/* Key values in command field */ +#define KEY_STREAM0 0 /* usual data stream */ +#define KEY_STREAM1 0x100 /* control/status stream */ +#define KEY_STREAM2 0x200 /* device-dependent stream */ +#define KEY_STREAM3 0x300 /* device-dependent stream */ +#define KEY_REGS 0x500 /* device register space */ +#define KEY_SYSTEM 0x600 /* system memory-mapped space */ +#define KEY_DEVICE 0x700 /* device memory-mapped space */ + +/* Interrupt control values in command field */ +#define INTR_NEVER 0 /* don't interrupt */ +#define INTR_IFSET 0x10 /* intr if condition bit is 1 */ +#define INTR_IFCLR 0x20 /* intr if condition bit is 0 */ +#define INTR_ALWAYS 0x30 /* always interrupt */ + +/* Branch control values in command field */ +#define BR_NEVER 0 /* don't branch */ +#define BR_IFSET 0x4 /* branch if condition bit is 1 */ +#define BR_IFCLR 0x8 /* branch if condition bit is 0 */ +#define BR_ALWAYS 0xc /* always branch */ + +/* Wait control values in command field */ +#define WAIT_NEVER 0 /* don't wait */ +#define WAIT_IFSET 1 /* wait if condition bit is 1 */ +#define WAIT_IFCLR 2 /* wait if condition bit is 0 */ +#define WAIT_ALWAYS 3 /* always wait */ + +/* Align an address for a DBDMA command structure */ +#define DBDMA_ALIGN(x) (((unsigned)(x) + sizeof(struct dbdma_cmd) - 1) \ + & -sizeof(struct dbdma_cmd)) +#endif /* _ASM_DBDMA_H_ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h --- v2.1.50/linux/include/asm-ppc/dma.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/dma.h Sat Aug 16 09:51:09 1997 @@ -23,6 +23,12 @@ #ifndef _ASM_DMA_H #define _ASM_DMA_H +#define MAX_DMA_CHANNELS 8 + +/* The maximum address that we can perform a DMA transfer to on this platform */ +/* Doesn't really apply... */ +#define MAX_DMA_ADDRESS 0xFFFFFFFF + #ifdef CONFIG_PREP #include /* need byte IO */ @@ -83,11 +89,8 @@ * */ -#define MAX_DMA_CHANNELS 8 - -/* The maximum address that we can perform a DMA transfer to on this platform */ -/* Doesn't really apply... */ -#define MAX_DMA_ADDRESS 0xFFFFFFFF +#define POWERSTACK_SND_DMA 6 +#define POWERSTACK_SND_DMA2 7 /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ @@ -150,6 +153,9 @@ #define DMA_HI_PAGE_6 0x489 #define DMA_HI_PAGE_7 0x48A +#define DMA1_EXT_REG 0x40B +#define DMA2_EXT_REG 0x4D6 + #define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ #define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ #define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ @@ -214,9 +220,11 @@ switch(dmanr) { case 0: dma_outb(pagenr, DMA_LO_PAGE_0); + dma_outb(pagenr>>8, DMA_HI_PAGE_0); break; case 1: dma_outb(pagenr, DMA_LO_PAGE_1); + dma_outb(pagenr>>8, DMA_HI_PAGE_1); break; case 2: dma_outb(pagenr, DMA_LO_PAGE_2); @@ -225,15 +233,24 @@ case 3: dma_outb(pagenr, DMA_LO_PAGE_3); break; - case 5: + case 5: dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); + dma_outb(pagenr>>8, DMA_HI_PAGE_5); break; case 6: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); + if (POWERSTACK_SND_DMA == 6 || POWERSTACK_SND_DMA2 == 6) + dma_outb(pagenr, DMA_LO_PAGE_6); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); + dma_outb(pagenr>>8, DMA_HI_PAGE_6); break; case 7: - dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); - break; + if (POWERSTACK_SND_DMA == 7 || POWERSTACK_SND_DMA2 == 7) + dma_outb(pagenr, DMA_LO_PAGE_7); + else + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); + dma_outb(pagenr>>8, DMA_HI_PAGE_7); + break; } } @@ -247,8 +264,14 @@ dma_outb( phys & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); } else { + if (dmanr == POWERSTACK_SND_DMA || dmanr == POWERSTACK_SND_DMA2) { + dma_outb( phys & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (dmanr&3), DMA2_EXT_REG); + } else { dma_outb( (phys>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); dma_outb( (phys>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } } set_dma_page(dmanr, phys>>16); } @@ -269,8 +292,13 @@ dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); } else { + if (dmanr == POWERSTACK_SND_DMA || dmanr == POWERSTACK_SND_DMA2) { + dma_outb( count & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } else { dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } } } @@ -297,10 +325,14 @@ return (dmanr<=3)? count : (count<<1); } +#else /* CONFIG_PREP */ -/* These are in kernel/dma.c: */ -extern void free_dma(unsigned int dmanr); /* release it again */ +#define DMA_MODE_READ 1 +#define DMA_MODE_WRITE 2 #endif /* CONFIG_PREP */ + +/* These are in kernel/dma.c: */ +extern void free_dma(unsigned int dmanr); /* release it again */ #endif /* _ASM_DMA_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h --- v2.1.50/linux/include/asm-ppc/elf.h Wed Dec 18 00:54:09 1996 +++ linux/include/asm-ppc/elf.h Sat Aug 16 09:51:09 1997 @@ -6,8 +6,8 @@ */ #include -#define ELF_NGREG 32 -#define ELF_NFPREG 32 +#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ +#define ELF_NFPREG 33 /* includes fpscr */ /* * This is used to ensure we don't load something for the wrong architecture. @@ -29,5 +29,10 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +#define ELF_CORE_COPY_REGS(gregs, regs) \ + memcpy(gregs, regs, \ + sizeof(struct pt_regs) < sizeof(elf_gregset_t)? \ + sizeof(struct pt_regs): sizeof(elf_gregset_t)); #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h --- v2.1.50/linux/include/asm-ppc/ide.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/ide.h Sat Aug 16 09:51:09 1997 @@ -107,7 +107,7 @@ return index; } -extern void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq); +void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq); typedef union { unsigned all : 8; /* all of the bits together */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h --- v2.1.50/linux/include/asm-ppc/io.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/io.h Sat Aug 16 09:51:09 1997 @@ -5,7 +5,6 @@ #include #include -#ifdef CONFIG_PREP /* from the Carolina Technical Spec -- Cort */ #define IBM_ACORN 0x82A #define SIO_CONFIG_RA 0x398 @@ -17,68 +16,49 @@ #define IBM_L2_INVALIDATE 0x814 #define IBM_SYS_CTL 0x81c +extern unsigned long io_base; #define SLOW_DOWN_IO -#ifndef PCI_DRAM_OFFSET -#define PCI_DRAM_OFFSET 0x80000000 -#endif +#define _IO_BASE io_base +#undef PCI_DRAM_OFFSET +#define PCI_DRAM_OFFSET _IO_BASE #define readb(addr) (*(volatile unsigned char *) (addr)) -#define readw(addr) (*(volatile unsigned short *) (addr)) -#define readl(addr) (*(volatile unsigned int *) (addr)) +#define readw(addr) ld_le16((volatile unsigned short *)(addr)) +#define readl(addr) ld_le32(addr) #define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) -#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) -#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) +#define writew(b,addr) st_le16((volatile unsigned short *)(addr),(b)) +#define writel(b,addr) st_le32((addr),(b)) -void outsl(int port, long *ptr, int len); - -__inline__ unsigned char outb(unsigned char val, int port); -__inline__ unsigned short outw(unsigned short val, int port); -__inline__ unsigned long outl(unsigned long val, int port); -__inline__ unsigned char inb(int port); -__inline__ unsigned short inw(int port); -__inline__ unsigned long inl(int port); - -#define inb_p inb -#define inw_p inw -#define inl_p inl -#define outb_p outb -#define outw_p outw -#define outl_p outl - -#endif /* CONFIG_PREP */ - -#ifdef CONFIG_PMAC -/* - * Read and write the non-volatile RAM. - */ -extern int nvram_readb(int addr); -extern void nvram_writeb(int addr, int val); - -#ifndef PCI_DRAM_OFFSET -#define PCI_DRAM_OFFSET 0 -#endif - -#define inb(port) in_8((unsigned char *)(port)) -#define outb(val, port) out_8((unsigned char *)(port), (val)) -#define inw(port) in_le16((unsigned short *)(port)) -#define outw(val, port) out_le16((unsigned short *)(port), (val)) -#define inl(port) in_le32((unsigned long *)(port)) -#define outl(val, port) out_le32((unsigned long *)(port), (val)) - -#define inb_p(port) in_8((unsigned char *)(port)) -#define outb_p(val, port) out_8((unsigned char *)(port), (val)) -#define inw_p(port) in_le16((unsigned short *)(port)) -#define outw_p(val, port) out_le16((unsigned short *)(port), (val)) -#define inl_p(port) in_le32(((unsigned long *)port)) -#define outl_p(val, port) out_le32((unsigned long *)(port), (val)) - -#define insw(port, buf, ns) _insw((unsigned short *)(port), (buf), (ns)) -#define outsw(port, buf, ns) _outsw((unsigned short *)(port), (buf), (ns)) -#define insl(port, buf, nl) _insl((unsigned long *)(port), (buf), (nl)) -#define outsl(port, buf, nl) _outsl((unsigned long *)(port), (buf), (nl)) -#endif /* CONFIG_PMAC */ +#define insb(port, buf, ns) _insb((unsigned char *)((port)+_IO_BASE), (buf), (ns)) +#define outsb(port, buf, ns) _outsb((unsigned char *)((port)+_IO_BASE), (buf), (ns)) +#define insw(port, buf, ns) _insw((unsigned short *)((port)+_IO_BASE), (buf), (ns)) +#define outsw(port, buf, ns) _outsw((unsigned short *)((port)+_IO_BASE), (buf), (ns)) +#define insl(port, buf, nl) _insl((unsigned long *)((port)+_IO_BASE), (buf), (nl)) +#define outsl(port, buf, nl) _outsl((unsigned long *)((port)+_IO_BASE), (buf), (nl)) + +#define inb(port) in_8((unsigned char *)((port)+_IO_BASE)) +#define outb(val, port) out_8((unsigned char *)((port)+_IO_BASE), (val)) +#define inw(port) in_le16((unsigned short *)((port)+_IO_BASE)) +#define outw(val, port) out_le16((unsigned short *)((port)+_IO_BASE), (val)) +#define inl(port) in_le32((unsigned *)((port)+_IO_BASE)) +#define outl(val, port) out_le32((unsigned *)((port)+_IO_BASE), (val)) + +#define inb_p(port) in_8((unsigned char *)((port)+_IO_BASE)) +#define outb_p(val, port) out_8((unsigned char *)((port)+_IO_BASE), (val)) +#define inw_p(port) in_le16((unsigned short *)((port)+_IO_BASE)) +#define outw_p(val, port) out_le16((unsigned short *)((port)+_IO_BASE), (val)) +#define inl_p(port) in_le32(((unsigned *)port)) +#define outl_p(val, port) out_le32((unsigned *)((port)+_IO_BASE), (val)) + +extern void _insb(volatile unsigned char *port, void *buf, int ns); +extern void _outsb(volatile unsigned char *port, const void *buf, int ns); +extern void _insw(volatile unsigned short *port, void *buf, int ns); +extern void _outsw(volatile unsigned short *port, const void *buf, int ns); +extern void _insl(volatile unsigned long *port, void *buf, int nl); +extern void _outsl(volatile unsigned long *port, const void *buf, int nl); +#ifdef __KERNEL__ /* * The PCI bus is inherently Little-Endian. The PowerPC is being * run Big-Endian. Thus all values which cross the [PCI] barrier @@ -88,14 +68,16 @@ */ extern inline unsigned long virt_to_bus(volatile void * address) { - if (address == (void *)0) return 0; - return ((unsigned long)((long)address - KERNELBASE + PCI_DRAM_OFFSET)); + if (address == (void *)0) + return 0; + return (unsigned long)address - KERNELBASE + PCI_DRAM_OFFSET; } extern inline void * bus_to_virt(unsigned long address) { - if (address == 0) return 0; - return ((void *)(address - PCI_DRAM_OFFSET + KERNELBASE)); + if (address == 0) + return 0; + return (void *)(address - PCI_DRAM_OFFSET + KERNELBASE); } /* @@ -105,29 +87,20 @@ extern void *ioremap(unsigned long address, unsigned long size); /* - * Change virtual addresses to physical addresses and vv. - * These are trivial on the 1:1 Linux/i386 mapping (but if we ever - * make the kernel segment mapped at 0, we need to do translation - * on the i386 as well) + * Change virtual addresses to physical addresses and vv, for + * addresses in the area where the kernel has the RAM mapped. */ extern inline unsigned long virt_to_phys(volatile void * address) { - return (unsigned long) address; + return (unsigned long) address - KERNELBASE; } extern inline void * phys_to_virt(unsigned long address) { - return (void *) address; + return (void *) (address + KERNELBASE); } -#define _IO_BASE ((unsigned long)0x80000000) - -/* - * These are much more useful le/be io functions from Paul - * than leXX_to_cpu() style functions since the ppc has - * load/store byte reverse instructions - * -- Cort - */ +#endif /* __KERNEL__ */ /* * Enforce In-order Execution of I/O: diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ioctls.h linux/include/asm-ppc/ioctls.h --- v2.1.50/linux/include/asm-ppc/ioctls.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/ioctls.h Sat Aug 16 09:51:09 1997 @@ -83,8 +83,8 @@ #define TIOCGETD 0x5424 #define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ #define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ -#define TIOCSBRK 0x5427 /* BSD compatibility */ -#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ipc.h linux/include/asm-ppc/ipc.h --- v2.1.50/linux/include/asm-ppc/ipc.h Wed Dec 18 00:54:09 1996 +++ linux/include/asm-ppc/ipc.h Sat Aug 16 09:51:09 1997 @@ -1,10 +1,10 @@ -#ifndef __i386_IPC_H__ -#define __i386_IPC_H__ +#ifndef __PPC_IPC_H__ +#define __PPC_IPC_H__ /* - * These are used to wrap system calls on x86. + * These are used to wrap system calls on PowerPC. * - * See arch/i386/kernel/sys_i386.c for ugly details.. + * See arch/ppc/kernel/syscalls.c for ugly details.. */ struct ipc_kludge { struct msgbuf *msgp; @@ -25,4 +25,4 @@ #define IPCCALL(version,op) ((version)<<16 | (op)) -#endif +#endif /* __PPC_IPC_H__ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h --- v2.1.50/linux/include/asm-ppc/irq.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/irq.h Sat Aug 16 09:51:09 1997 @@ -3,11 +3,7 @@ #include -#ifdef CONFIG_PMAC -#define NR_IRQS 32 -#else -#define NR_IRQS 16 -#endif +#define NR_IRQS 32 extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h --- v2.1.50/linux/include/asm-ppc/linux_logo.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/linux_logo.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,914 @@ +/* + * include/asm-ppc/linux_logo.h: A linux logo to be displayed on boot + * (pinched from the sparc port). + * + * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu) + * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * You can put anything here, but: + * LINUX_LOGO_COLORS has to be less than 224 + * values have to start from 0x20 + * (i.e. linux_logo_{red,green,blue}[0] is color 0x20) + */ + +#include + +#define LINUX_LOGO_HEIGHT 80 +#define LINUX_LOGO_WIDTH 80 +#define LINUX_LOGO_COLORS 221 + +unsigned char linux_logo_red[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, + 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, + 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, + 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, + 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, + 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, + 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, + 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, + 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, + 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, + 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, + 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, + 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, + 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, + 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, + 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, + 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, + 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo_green[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, + 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, + 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, + 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, + 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, + 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, + 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, + 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, + 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, + 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, + 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, + 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, + 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, + 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, + 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, + 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, + 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, + 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo_blue[] __initdata = { + 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, + 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, + 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, + 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, + 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, + 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, + 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, + 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, + 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, + 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, + 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, + 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, + 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, + 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, + 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, + 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, + 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, + 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, + 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, + 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, + 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, + 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, + 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, + 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, + 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, + 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, + 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, + 0x1D, 0x14, 0x06, 0x02, 0x00 +}; + +unsigned char linux_logo[] __initdata = { + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, + 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, + 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, + 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, + 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, + 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, + 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, + 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, + 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, + 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, + 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, + 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, + 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, + 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, + 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, + 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, + 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, + 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, + 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, + 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, + 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, + 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, + 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, + 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, + 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, + 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, + 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, + 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, + 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, + 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, + 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, + 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, + 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, + 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, + 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, + 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, + 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, + 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, + 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, + 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, + 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, + 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, + 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, + 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, + 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, + 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, + 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, + 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, + 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, + 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, + 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, + 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, + 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, + 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, + 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, + 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, + 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, + 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, + 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, + 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, + 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, + 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, + 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, + 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, + 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, + 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, + 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, + 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, + 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, + 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, + 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, + 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, + 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, + 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, + 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, + 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, + 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, + 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, + 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, + 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, + 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, + 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, + 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, + 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, + 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, + 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, + 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, + 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, + 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, + 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, + 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, + 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, + 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, + 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, + 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, + 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, + 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, + 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, + 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, + 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, + 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, + 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, + 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, + 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, + 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, + 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, + 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, + 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, + 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, + 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, + 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, + 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, + 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, + 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, + 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, + 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, + 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, + 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, + 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, + 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, + 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, + 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, + 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, + 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, + 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, + 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, + 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, + 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, + 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, + 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, + 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, + 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, + 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, + 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, + 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, + 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, + 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, + 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, + 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, + 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, + 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, + 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, + 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, + 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, + 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, + 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, + 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, + 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, + 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, + 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, + 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, + 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, + 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, + 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, + 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, + 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, + 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, + 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, + 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, + 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, + 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, + 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, + 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, + 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, + 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, + 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, + 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, + 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, + 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, + 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, + 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, + 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, + 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, + 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, + 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, + 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, + 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, + 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, + 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, + 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, + 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, + 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, + 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, + 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, + 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, + 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, + 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, + 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, + 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, + 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, + 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, + 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, + 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, + 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, + 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, + 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, + 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, + 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, + 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, + 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, + 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, + 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, + 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, + 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, + 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, + 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, + 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, + 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, + 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, + 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, + 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, + 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, + 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, + 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, + 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, + 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, + 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, + 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, + 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, + 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, + 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, + 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, + 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, + 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, + 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, + 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, + 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, + 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, + 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, + 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, + 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, + 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, + 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, + 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, + 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, + 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, + 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, + 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, + 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, + 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, + 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, + 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, + 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, + 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, + 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, + 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, + 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, + 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, + 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, + 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, + 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, + 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, + 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, + 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, + 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, + 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, + 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, + 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, + 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, + 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, + 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, + 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, + 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, + 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, + 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, + 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, + 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, + 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, + 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, + 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, + 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, + 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, + 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, + 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, + 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, + 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, + 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, + 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, + 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, + 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, + 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, + 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, + 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, + 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, + 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, + 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, + 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, + 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, + 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, + 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, + 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, + 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, + 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, + 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, + 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, + 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, + 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, + 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, + 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, + 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, + 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, + 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, + 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, + 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, + 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, + 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, + 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, + 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, + 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, + 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, + 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, + 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, + 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, + 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, + 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, + 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, + 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, + 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, + 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, + 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, + 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, + 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, + 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, + 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, + 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, + 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, + 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, + 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, + 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, + 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, + 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, + 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, + 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, + 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, + 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, + 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, + 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, + 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, + 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, + 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, + 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, + 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, + 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, + 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, + 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, + 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, + 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, + 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, + 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, + 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, + 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, + 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, + 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, + 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, + 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, + 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, + 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, + 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, + 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, + 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, + 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, + 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, + 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, + 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, + 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, + 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, + 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, + 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, + 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, + 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, + 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, + 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, + 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, + 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, + 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, + 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, + 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, + 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, + 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, + 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, + 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, + 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, + 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, + 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, + 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, + 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, + 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, + 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, + 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, + 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, + 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, + 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, + 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, + 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, + 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, + 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, + 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, + 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, + 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, + 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, + 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, + 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, + 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, + 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, + 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, + 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, + 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, + 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, + 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, + 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, + 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, + 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, + 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, + 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, + 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, + 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, + 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, + 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, + 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, + 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, + 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, + 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, + 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, + 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, + 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, + 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, + 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, + 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, + 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, + 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, + 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, + 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, + 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, + 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, + 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, + 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, + 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, + 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, + 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, + 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, + 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, + 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, + 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, + 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, + 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, + 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, + 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, + 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, + 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, + 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, + 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, + 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, + 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, + 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, + 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, + 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, + 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, + 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, + 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, + 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, + 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, + 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, + 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, + 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, + 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, + 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, + 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, + 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, + 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, + 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, + 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, + 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, + 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, + 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, + 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, + 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, + 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, + 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, + 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, + 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, + 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, + 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, + 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, + 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, + 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, + 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, + 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, + 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, + 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, + 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, + 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, + 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, + 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, + 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, + 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, + 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, + 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, + 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, + 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, + 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, + 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, + 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, + 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, + 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, + 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, + 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, + 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, + 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, + 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, + 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, + 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, + 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, + 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, + 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, + 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, + 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, + 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, + 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, + 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, + 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, + 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, + 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, + 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, + 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, + 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, + 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, + 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, + 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, + 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, + 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, + 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, + 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, + 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, + 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, + 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, + 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, + 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, + 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, + 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, + 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, + 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, + 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, + 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, + 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, + 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, + 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, + 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, + 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, + 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, + 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, + 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, + 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, + 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, + 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, + 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, + 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, + 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, + 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, + 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, + 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, + 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, + 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, + 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, + 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, + 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, + 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, + 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, + 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, + 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, + 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, + 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, + 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, + 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, + 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, + 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, + 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, + 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, + 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, + 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, + 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, + 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, + 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, + 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, + 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, + 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, + 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, + 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, + 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, + 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, + 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, + 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, + 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, + 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, + 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, + 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, + 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, + 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, + 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, + 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, + 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, + 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, + 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, + 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, + 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, + 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, + 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, + 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, + 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, + 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, + 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, + 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, + 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, + 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, + 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, + 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, + 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, + 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, + 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, + 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, + 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, + 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, + 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, + 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, + 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, + 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, + 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, + 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, + 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, + 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, + 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, + 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, +}; diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h --- v2.1.50/linux/include/asm-ppc/mmu.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/mmu.h Sat Aug 16 09:51:09 1997 @@ -144,7 +144,7 @@ pte **pmap; /* Two-level page-map structure */ } MMU_context; -/* Used to set up SDR register */ +/* Used to set up SDR1 register */ #define HASH_TABLE_SIZE_64K 0x00010000 #define HASH_TABLE_SIZE_128K 0x00020000 #define HASH_TABLE_SIZE_256K 0x00040000 @@ -159,5 +159,13 @@ #define HASH_TABLE_MASK_1M 0x00F #define HASH_TABLE_MASK_2M 0x01F #define HASH_TABLE_MASK_4M 0x03F + +/* invalidate a TLB entry */ +extern inline void _tlbie(unsigned long va) +{ + asm volatile ("tlbie %0" : : "r"(va)); +} + +extern void _tlbia(void); /* invalidate all TLB entries */ #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h --- v2.1.50/linux/include/asm-ppc/mmu_context.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/mmu_context.h Sat Aug 16 09:51:09 1997 @@ -29,7 +29,6 @@ do { \ struct mm_struct *mm = (tsk)->mm; \ if (mm->context == NO_CONTEXT) { \ - int i; \ if (next_mmu_context == LAST_CONTEXT) \ mmu_context_overflow(); \ mm->context = MUNGE_CONTEXT(++next_mmu_context);\ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/namei.h linux/include/asm-ppc/namei.h --- v2.1.50/linux/include/asm-ppc/namei.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/namei.h Sat Aug 16 09:51:09 1997 @@ -1,11 +1,12 @@ -/* $Id: namei.h,v 1.1 1997/07/25 09:28:40 cort Exp $ - * linux/include/asm-i386/namei.h +/* $Id: namei.h,v 1.2 1997/07/31 07:10:55 paulus Exp $ + * linux/include/asm-ppc/namei.h + * Adapted from linux/include/asm-alpha/namei.h * * Included from linux/fs/namei.c */ -#ifndef __I386_NAMEI_H -#define __I386_NAMEI_H +#ifndef __PPC_NAMEI_H +#define __PPC_NAMEI_H /* These dummy routines maybe changed to something useful * for /usr/gnemul/ emulation stuff. @@ -18,4 +19,4 @@ #define translate_open_namei(pathname, flag, mode, res_inode, base) \ do { } while (0) -#endif /* __I386_NAMEI_H */ +#endif /* __PPC_NAMEI_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/nvram.h linux/include/asm-ppc/nvram.h --- v2.1.50/linux/include/asm-ppc/nvram.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/nvram.h Sat Aug 16 09:51:09 1997 @@ -12,15 +12,15 @@ /* RTC Offsets */ -#define RTC_SECONDS 0x1FF9 -#define RTC_MINUTES 0x1FFA -#define RTC_HOURS 0x1FFB -#define RTC_DAY_OF_WEEK 0x1FFC -#define RTC_DAY_OF_MONTH 0x1FFD -#define RTC_MONTH 0x1FFE -#define RTC_YEAR 0x1FFF -#define RTC_CONTROLA 0x1FF8 -#define RTC_CONTROLB 0x1FF9 +#define MOTO_RTC_SECONDS 0x1FF9 +#define MOTO_RTC_MINUTES 0x1FFA +#define MOTO_RTC_HOURS 0x1FFB +#define MOTO_RTC_DAY_OF_WEEK 0x1FFC +#define MOTO_RTC_DAY_OF_MONTH 0x1FFD +#define MOTO_RTC_MONTH 0x1FFE +#define MOTO_RTC_YEAR 0x1FFF +#define MOTO_RTC_CONTROLA 0x1FF8 +#define MOTO_RTC_CONTROLB 0x1FF9 #ifndef BCD_TO_BIN #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h --- v2.1.50/linux/include/asm-ppc/page.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/page.h Sat Aug 16 09:51:09 1997 @@ -81,14 +81,14 @@ #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) -/* map phys->virtual and virtual->phys */ +/* map phys->virtual and virtual->phys for RAM pages */ #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT) +#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT) #define MAP_PAGE_RESERVED (1<<15) -extern __inline__ unsigned long get_prezerod_page(void); +extern unsigned long get_prezerod_page(void); #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/pci-bridge.h linux/include/asm-ppc/pci-bridge.h --- v2.1.50/linux/include/asm-ppc/pci-bridge.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/pci-bridge.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,20 @@ +#ifndef _ASM_PCI_BRIDGE_H +#define _ASM_PCI_BRIDGE_H + +unsigned long pmac_find_bridges(unsigned long, unsigned long); + +/* + * pci_io_base returns the memory address at which you can access + * the I/O space for PCI bus number `bus' (or NULL on error). + */ +void *pci_io_base(unsigned int bus); + +/* + * pci_device_loc returns the bus number and device/function number + * for a device on a PCI bus, given its device_node struct. + * It returns 0 if OK, -1 on error. + */ +int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, + unsigned char *devfn_ptr); + +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h --- v2.1.50/linux/include/asm-ppc/pgtable.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/pgtable.h Sat Aug 16 09:51:09 1997 @@ -1,22 +1,25 @@ #ifndef _PPC_PGTABLE_H #define _PPC_PGTABLE_H -#include -#include -#include +#include extern void flush_tlb_all(void); extern void flush_tlb_mm(struct mm_struct *mm); extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); -extern void flush_tlb(void); -/* Caches aren't brain-dead on the ppc. */ -#define flush_cache_all() -#define flush_cache_mm(mm) -#define flush_cache_range(mm, start, end) -#define flush_cache_page(vma, vmaddr) +/* + * No cache flushing is required when address mappings are + * changed, because the caches on PowerPCs are physically + * addressed. + */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_range(mm, a, b) do { } while (0) +#define flush_cache_page(vma, p) do { } while (0) +extern void flush_icache_range(unsigned long, unsigned long); + /* * For the page specified, write modified lines in the data cache * out to memory, and invalidate lines in the instruction cache. @@ -25,6 +28,20 @@ extern unsigned long va_to_phys(unsigned long address); +/* + * The PowerPC MMU uses a hash table containing PTEs, together with + * a set of 16 segment registers (on 32-bit implementations), to define + * the virtual to physical address mapping. + * + * We use the hash table as an extended TLB, i.e. a cache of currently + * active mappings. We maintain a two-level page table tree, much like + * that used by the i386, for the sake of the Linux memory management code. + * Low-level assembler code in head.S (procedure hash_page) is responsible + * for extracting ptes from the tree and putting them into the hash table + * when necessary, and updating the accessed and modified bits in the + * page table tree. + */ + /* PMD_SHIFT determines the size of the area mapped by the second-level page tables */ #define PMD_SHIFT 22 #define PMD_SIZE (1UL << PMD_SHIFT) @@ -133,9 +150,7 @@ /* to set the page-dir */ /* tsk is a task_struct and pgdir is a pte_t */ -#define SET_PAGE_DIR(tsk,pgdir) ({ \ - ((tsk)->tss.pg_tables = (unsigned long *)(pgdir)); \ -}) +#define SET_PAGE_DIR(tsk,pgdir) extern inline int pte_none(pte_t pte) { return !pte_val(pte); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } @@ -146,7 +161,7 @@ extern inline int pmd_present(pmd_t pmd) { return (pmd_val(pmd) & PAGE_MASK) != 0; } extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } - + /* * The "pgd_xxx()" functions here are trivial for a folded two-level * setup: the pgd is never bad, and a pmd always exists (as it's folded @@ -370,13 +385,27 @@ * as entries are faulted into the hash table by the low-level * data/instruction access exception handlers. */ -#define update_mmu_cache(vma,address,pte) while(0){} +#define update_mmu_cache(vma, addr, pte) do { } while (0) +/* + * When flushing the tlb entry for a page, we also need to flush the + * hash table entry. flush_hash_page is assembler (for speed) in head.S. + */ +extern void flush_hash_segments(unsigned low_vsid, unsigned high_vsid); +extern void flush_hash_page(unsigned context, unsigned long va); + +extern inline void +flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) +{ + if (vmaddr < TASK_SIZE) + flush_hash_page(vma->vm_mm->context, vmaddr); +} #define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) #define SWP_OFFSET(entry) ((entry) >> 8) #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) +#define module_map vmalloc +#define module_unmap vfree - -#endif /* _PPC_PAGE_H */ +#endif /* _PPC_PGTABLE_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/poll.h linux/include/asm-ppc/poll.h --- v2.1.50/linux/include/asm-ppc/poll.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/poll.h Sat Aug 16 09:51:09 1997 @@ -1,15 +1,12 @@ -#ifndef __i386_POLL_H -#define __i386_POLL_H +#ifndef __PPC_POLL_H +#define __PPC_POLL_H -/* These are specified by iBCS2 */ #define POLLIN 0x0001 #define POLLPRI 0x0002 #define POLLOUT 0x0004 #define POLLERR 0x0008 #define POLLHUP 0x0010 #define POLLNVAL 0x0020 - -/* The rest seem to be more-or-less nonstandard. Check them! */ #define POLLRDNORM 0x0040 #define POLLRDBAND 0x0080 #define POLLWRNORM 0x0100 diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.1.50/linux/include/asm-ppc/processor.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/processor.h Sat Aug 16 09:51:09 1997 @@ -1,8 +1,7 @@ #ifndef __ASM_PPC_PROCESSOR_H #define __ASM_PPC_PROCESSOR_H -#include - +#include /* Bit encodings for Machine State Register (MSR) */ #define MSR_POW (1<<18) /* Enable Power Management */ @@ -22,11 +21,12 @@ #define MSR_RI (1<<1) /* Recoverable Exception */ #define MSR_LE (1<<0) /* Little-Endian enable */ -#define MSR_ MSR_FE0|MSR_FE1|MSR_ME +#define MSR_ MSR_ME|MSR_FE0|MSR_FE1|MSR_RI #define MSR_KERNEL MSR_|MSR_IR|MSR_DR -#define MSR_USER MSR_FE0|MSR_FE1|MSR_ME|MSR_PR|MSR_EE|MSR_IR|MSR_DR +#define MSR_USER MSR_KERNEL|MSR_PR|MSR_EE -/* Bit encodings for Hardware Implementation Register (HID0) */ +/* Bit encodings for Hardware Implementation Register (HID0) + on PowerPC 603, 604, etc. processors (not 601). */ #define HID0_EMCP (1<<31) /* Enable Machine Check pin */ #define HID0_EBA (1<<29) /* Enable Bus Address Parity */ #define HID0_EBD (1<<28) /* Enable Bus Data Parity */ @@ -46,15 +46,19 @@ #define HID0_DCI (1<<10) /* Data Cache Invalidate */ #define HID0_SIED (1<<7) /* Serial Instruction Execution [Disable] */ #define HID0_BHTE (1<<2) /* Branch History Table Enable */ + /* fpscr settings */ #define FPSCR_FX (1<<31) #define FPSCR_FEX (1<<30) + #ifndef __ASSEMBLY__ /* * PowerPC machine specifics */ -extern inline void start_thread(struct pt_regs *, unsigned long, unsigned long ); +struct task_struct; +void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); +void release_thread(struct task_struct *); /* * Bus types @@ -70,49 +74,37 @@ #define wp_works_ok 1 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */ +/* + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. + */ #define TASK_SIZE (0x80000000UL) + /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -struct thread_struct -{ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3) + +struct thread_struct { unsigned long ksp; /* Kernel stack pointer */ - unsigned long *pg_tables; /* MMU information */ -#ifdef CONFIG_PMAC - unsigned long last_pc; /* PC when last entered system */ - unsigned long user_stack; /* [User] Stack when entered kernel */ -#endif - unsigned long fpscr_pad; /* (so we can save fpscr with stfd) */ - unsigned long fpscr; /* fp status reg */ - double fpr[32]; /* Complete floating point set */ - unsigned long fp_used; unsigned long wchan; /* Event task is sleeping on */ - struct pt_regs *regs; /* Pointer to saved register state */ + struct pt_regs *regs; /* Pointer to saved register state */ unsigned long fs; /* for get_fs() validation */ signed long last_syscall; - unsigned long pad[2]; /* pad to 16-byte boundry */ + double fpr[32]; /* Complete floating point set */ + unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */ + unsigned long fpscr; /* Floating point status */ }; -/* Points to the thread_struct of the thread (if any) which - currently owns the FPU. */ -#define fpu_tss (&(last_task_used_math->tss)) - -#ifdef CONFIG_PMAC -#define LAZY_TSS_FPR_INIT 0,0,0,0,{0}, -#endif -#ifdef CONFIG_PREP -#define LAZY_TSS_FPR_INIT 0,0,{0}, -#endif +#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) #define INIT_TSS { \ - sizeof(init_stack) + (long) &init_stack, /* ksp */ \ - (long *)swapper_pg_dir, /* pg_tables */ \ - LAZY_TSS_FPR_INIT \ - 0, /*fp_used*/ 0, /*wchan*/ \ - sizeof(init_stack) + (long)&init_stack - \ - sizeof(struct pt_regs), /* regs */ \ - KERNEL_DS /*fs*/, 0 /*last_syscall*/ \ + INIT_SP, /* ksp */ \ + 0, /* wchan */ \ + (struct pt_regs *)INIT_SP - 1, /* regs */ \ + KERNEL_DS, /*fs*/ \ + 0, /* last_syscall */ \ + {0}, 0, 0 \ } #define INIT_MMAP { &init_mm, KERNELBASE/*0*/, 0xffffffff/*0x40000000*/, \ @@ -124,15 +116,8 @@ static inline unsigned long thread_saved_pc(struct thread_struct *t) { return (t->regs) ? t->regs->nip : 0; - /*return (t->last_pc);*/ } -extern int _machine; -#define _MACH_Motorola 0 -#define _MACH_IBM 1 -#define _MACH_Be 2 -#define _MACH_Pmac 3 - /* * NOTE! The task struct and the stack go together */ @@ -144,7 +129,15 @@ int ll_printk(const char *, ...); void ll_puts(const char *); +extern int _machine; #endif /* ndef ASSEMBLY*/ + +#define _MACH_Motorola 1 /* motorola prep */ +#define _MACH_IBM 2 /* ibm prep */ +#define _MACH_Pmac 4 /* pmac or pmac clone */ +#define _MACH_chrp 8 /* chrp machine */ + +#define is_prep ((_machine == _MACH_Motorola)||(_machine == _MACH_IBM)) #define init_task (init_task_union.task) #define init_stack (init_task_union.stack) diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h --- v2.1.50/linux/include/asm-ppc/prom.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/prom.h Sat Aug 16 09:51:09 1997 @@ -0,0 +1,65 @@ +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + */ + +typedef void *phandle; +typedef void *ihandle; + +extern ihandle prom_stdout; +extern ihandle prom_chosen; +extern phandle cpu_node; +extern char prom_display_path[]; + +struct reg_property { + unsigned int address; + unsigned int size; +}; + +struct translation_property { + unsigned int virt; + unsigned int size; + unsigned int phys; + unsigned int flags; +}; + +struct property { + char *name; + int length; + unsigned char *value; + struct property *next; +}; + +struct device_node { + char *name; + char *type; + phandle node; + int n_addrs; + struct reg_property *addrs; + int n_intrs; + int *intrs; + char *full_name; + struct property *properties; + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; + struct device_node *next; /* next device of same type */ + struct device_node *allnext; /* next in list of all nodes */ +}; + +/* Prototypes */ +void abort(void); +void prom_exit(void); +void *call_prom(const char *service, int nargs, int nret, ...); +void prom_print(const char *msg); +void prom_init(char *params, int unused, void (*)(void *)); +void set_prom_callback(void); +unsigned long copy_device_tree(unsigned long, unsigned long); +struct device_node *find_devices(const char *name); +struct device_node *find_type_devices(const char *type); +struct device_node *find_path_device(const char *path); +unsigned char *get_property(struct device_node *node, const char *name, + int *lenp); +void print_properties(struct device_node *node); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/ptrace.h linux/include/asm-ppc/ptrace.h --- v2.1.50/linux/include/asm-ppc/ptrace.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/ptrace.h Sat Aug 16 09:51:09 1997 @@ -2,63 +2,52 @@ #define _PPC_PTRACE_H /* + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry. + * * this should only contain volatile regs * since we can keep non-volatile in the tss * should set this up when only volatiles are saved * by intr code. * - * I can't find any reference to the above comment (from Gary Thomas) - * about _underhead/_overhead in the sys V abi for the ppc - * dated july 25, 1994. + * Since this is going on the stack, *CARE MUST BE TAKEN* to insure + * that the overall structure is a multiple of 16 bytes in length. * - * the stack must be kept to a size that is a multiple of 16 - * so this includes the stack frame overhead - * -- Cort. - */ - -/* - * GCC sometimes accesses words at negative offsets from the stack - * pointer, although the SysV ABI says it shouldn't. To cope with - * this, we leave this much untouched space on the stack on exception - * entry. + * Note that the offsets of the fields in this struct correspond with + * the PT_* values below. This simplifies arch/ppc/kernel/ptrace.c. */ -#define STACK_FRAME_OVERHEAD 16 -#define STACK_UNDERHEAD 64 #ifndef __ASSEMBLY__ struct pt_regs { unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long ctr; - unsigned long link; - unsigned long ccr; - unsigned long xer; - unsigned long dar; /* Fault registers */ - unsigned long dsisr; -#if 0 - unsigned long srr1; - unsigned long srr0; - unsigned long hash1, hash2; - unsigned long imiss, dmiss; - unsigned long icmp, dcmp; -#endif + unsigned long nip; + unsigned long msr; unsigned long orig_gpr3; /* Used for restarting system calls */ - unsigned long result; /* Result of a system call */ + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; + unsigned long mq; /* 601 only (not used at present) */ unsigned long trap; /* Reason for being here */ - unsigned long marker; /* Should have DEADDEAD */ + unsigned long dar; /* Fault registers */ + unsigned long dsisr; + unsigned long result; /* Result of a system call */ }; +#endif + +#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */ +/* Size of stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 64 #define instruction_pointer(regs) ((regs)->nip) #define user_mode(regs) ((regs)->msr & 0x4000) -#ifdef KERNEL -extern void show_regs(struct pt_regs *); -#endif -/* should include and generate these in ppc_defs.h -- Cort */ -/* Offsets used by 'ptrace' system call interface */ -/* Note: these should correspond to gpr[x] */ +/* + * Offsets used by 'ptrace' system call interface. + * These can't be changed without breaking binary compatibility + * with MkLinux, etc. + */ #define PT_R0 0 #define PT_R1 1 #define PT_R2 2 @@ -94,14 +83,18 @@ #define PT_NIP 32 #define PT_MSR 33 +#ifdef __KERNEL__ #define PT_ORIG_R3 34 +#endif #define PT_CTR 35 #define PT_LNK 36 #define PT_XER 37 #define PT_CCR 38 +#define PT_MQ 39 -#define PT_FPR0 48 -#endif /* __ASSEMBLY__ */ +#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ +#define PT_FPR31 (PT_FPR0 + 2*31) +#define PT_FPSCR (PT_FPR0 + 2*32 + 1) -#endif /* _PPC_PTRACE_H */ +#endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/residual.h linux/include/asm-ppc/residual.h --- v2.1.50/linux/include/asm-ppc/residual.h Wed Dec 18 00:54:10 1996 +++ linux/include/asm-ppc/residual.h Sat Aug 16 09:51:09 1997 @@ -311,5 +311,7 @@ unsigned char DevicePnPHeap[2*MAX_DEVICES*AVE_PNP_SIZE]; } RESIDUAL; + +extern RESIDUAL res; #endif /* ndef _RESIDUAL_ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/resource.h linux/include/asm-ppc/resource.h --- v2.1.50/linux/include/asm-ppc/resource.h Wed Dec 18 00:54:10 1996 +++ linux/include/asm-ppc/resource.h Sat Aug 16 09:51:09 1997 @@ -7,10 +7,10 @@ #define RLIMIT_STACK 3 /* max stack size */ #define RLIMIT_CORE 4 /* max core file size */ #define RLIMIT_RSS 5 /* max resident set size */ -#define RLIMIT_NOFILE 6 /* max number of open files */ -#define RLIMIT_AS 7 /* address space limit(?) */ -#define RLIMIT_NPROC 8 /* max number of processes */ -#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */ +#define RLIMIT_NPROC 6 /* max number of processes */ +#define RLIMIT_NOFILE 7 /* max number of open files */ +#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ +#define RLIMIT_AS 9 /* address space limit(?) */ #define RLIM_NLIMITS 10 @@ -24,10 +24,10 @@ {_STK_LIM, _STK_LIM}, /* RLIMIT_STACK */ \ { 0, LONG_MAX}, /* RLIMIT_CORE */ \ {LONG_MAX, LONG_MAX}, /* RLIMIT_RSS */ \ - { NR_OPEN, NR_OPEN}, /* RLIMIT_NOFILE */ \ - {LONG_MAX, LONG_MAX}, /* RLIMIT_AS */ \ {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER}, /* RLIMIT_NPROC */ \ + { NR_OPEN, NR_OPEN}, /* RLIMIT_NOFILE */ \ {LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \ + {LONG_MAX, LONG_MAX}, /* RLIMIT_AS */ \ } #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/scatterlist.h linux/include/asm-ppc/scatterlist.h --- v2.1.50/linux/include/asm-ppc/scatterlist.h Mon Dec 30 03:01:10 1996 +++ linux/include/asm-ppc/scatterlist.h Sat Aug 16 09:51:09 1997 @@ -1,6 +1,8 @@ #ifndef _PPC_SCATTERLIST_H #define _PPC_SCATTERLIST_H +#include + struct scatterlist { char * address; /* Location data is to be transferred to */ char * alt_address; /* Location of actual if address is a @@ -8,6 +10,18 @@ unsigned int length; }; +#ifdef CONFIG_PMAC +/* + * This is used in the scsi code to decide if bounce buffers are needed. + * Fortunately the dma controllers on the PowerMac are a bit better + * than on PCs... + */ +#define ISA_DMA_THRESHOLD (~0UL) +#endif + +#ifdef CONFIG_PREP +/* PReP systems are like PCs */ #define ISA_DMA_THRESHOLD (0x00ffffff) +#endif #endif /* !(_PPC_SCATTERLIST_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h --- v2.1.50/linux/include/asm-ppc/semaphore.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/semaphore.h Sat Aug 16 09:51:09 1997 @@ -44,13 +44,13 @@ __asm__ __volatile__( "1: lwarx %1,0,%2\n" " cmpwi 0,%1,0\n" - " addi %1,%1,-1\n" + " addic %1,%1,-1\n" " ble- 2f\n" " stwcx. %1,0,%2\n" " bne- 1b\n" - " mr %0,%1\n" + " li %0,1\n" "2:" - : "=r" (ret), "=r" (tmp) + : "=r" (ret), "=&r" (tmp) : "r" (&sem->waking), "0" (0) : "cr0", "memory"); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/socket.h linux/include/asm-ppc/socket.h --- v2.1.50/linux/include/asm-ppc/socket.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/socket.h Sat Aug 16 09:51:09 1997 @@ -34,4 +34,9 @@ #define SO_PASSCRED 20 #define SO_PEERCRED 21 +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + #endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/string.h linux/include/asm-ppc/string.h --- v2.1.50/linux/include/asm-ppc/string.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/string.h Sat Aug 16 09:51:09 1997 @@ -12,16 +12,7 @@ #define __HAVE_ARCH_MEMMOVE #define __HAVE_ARCH_MEMCMP #define __HAVE_ARCH_MEMCHR -/*#define bzero(addr,size) memset((addr),(int)(0),(size))*/ -extern inline void * memchr(const void * cs,int c,size_t count) -{ - unsigned long i = 0; - while ( count != i ) - { - if ( (char)c == *(char *)(cs + i) ) - return (void *)(cs + i); - i--; - } - return NULL; -} + +extern int strcasecmp(const char *, const char *); + #endif diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h --- v2.1.50/linux/include/asm-ppc/system.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/system.h Sat Aug 16 09:51:09 1997 @@ -1,40 +1,67 @@ #ifndef __PPC_SYSTEM_H #define __PPC_SYSTEM_H -#include +#include +#include #define mb() __asm__ __volatile__ ("sync" : : : "memory") #define __save_flags(flags) ({\ __asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory"); }) -/* using Paul's in misc.S now -- Cort */ -extern void __restore_flags(unsigned long flags); +extern __inline__ void __restore_flags(unsigned long flags) +{ + extern unsigned lost_interrupts; + extern void do_lost_interrupts(unsigned long); + if ((flags & MSR_EE) && lost_interrupts != 0) { + do_lost_interrupts(flags); + } else { + __asm__ __volatile__ ("sync; mtmsr %0; isync" + : : "r" (flags) : "memory"); + } +} + + +#if 0 /* - #define __sti() _soft_sti(void) - #define __cli() _soft_cli(void) + * Gcc bug prevents us from using this inline func so for now + * it lives in misc.S */ +void __inline__ __restore_flags(unsigned long flags) +{ + extern unsigned lost_interrupts; + __asm__ __volatile__ ( + "andi. 0,%0,%2 \n\t" + "beq 2f \n\t" + "cmpi 0,%1,0 \n\t" + "bne do_lost_interrupts \n\t" + "2: sync \n\t" + "mtmsr %0 \n\t" + "isync \n\t" + : + : "r" (flags), "r"(lost_interrupts), "i" (1<<15)/*MSR_EE*/ + : "0", "cc"); +} +#endif + extern void __sti(void); extern void __cli(void); - -extern void _hard_sti(void); -extern void _hard_cli(void); -extern void _soft_sti(void); -extern void _soft_cli(void); extern int _disable_interrupts(void); extern void _enable_interrupts(int); +extern void print_backtrace(unsigned long *); +extern void show_regs(struct pt_regs * regs); extern void flush_instruction_cache(void); extern void hard_reset_now(void); extern void poweroff_now(void); -extern void find_scsi_boot(void); +/*extern void note_bootable_part(kdev_t, int);*/ extern int sd_find_target(void *, int); extern int _get_PVR(void); extern void via_cuda_init(void); +extern void pmac_nvram_init(void); extern void read_rtc_time(void); extern void pmac_find_display(void); extern void giveup_fpu(void); -extern void store_cache_range(unsigned long, unsigned long); extern void cvt_fd(float *from, double *to); extern void cvt_df(double *from, float *to); diff -u --recursive --new-file v2.1.50/linux/include/asm-ppc/termbits.h linux/include/asm-ppc/termbits.h --- v2.1.50/linux/include/asm-ppc/termbits.h Mon Aug 4 16:25:39 1997 +++ linux/include/asm-ppc/termbits.h Sat Aug 16 09:51:09 1997 @@ -125,6 +125,7 @@ #define B57600 00020 #define B115200 00021 #define B230400 00022 +#define B460800 00023 #define CSIZE 00001400 #define CS5 00000000 diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h --- v2.1.50/linux/include/asm-sparc/pgtable.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc/pgtable.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.62 1997/06/27 14:55:00 jj Exp $ */ +/* $Id: pgtable.h,v 1.63 1997/08/13 04:44:15 paulus Exp $ */ #ifndef _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H @@ -298,6 +298,7 @@ extern void (*flush_cache_range)(struct mm_struct *, unsigned long start, unsigned long end); extern void (*flush_cache_page)(struct vm_area_struct *, unsigned long address); +#define flush_icache_range(start, end) do { } while (0) extern void (*flush_tlb_all)(void); extern void (*flush_tlb_mm)(struct mm_struct *); diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/atomic.h linux/include/asm-sparc64/atomic.h --- v2.1.50/linux/include/asm-sparc64/atomic.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/atomic.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: atomic.h,v 1.15 1997/07/03 09:18:09 davem Exp $ +/* $Id: atomic.h,v 1.18 1997/08/07 03:38:31 davem Exp $ * atomic.h: Thankfully the V9 is at least reasonable for this * stuff. * @@ -23,29 +23,29 @@ extern __inline__ void atomic_add(int i, atomic_t *v) { __asm__ __volatile__(" -1: lduw [%1], %%g1 - add %%g1, %0, %%g2 - cas [%1], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b +1: lduw [%1], %%g5 + add %%g5, %0, %%g7 + cas [%1], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b nop" : /* No outputs */ : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); } extern __inline__ void atomic_sub(int i, atomic_t *v) { __asm__ __volatile__(" -1: lduw [%1], %%g1 - sub %%g1, %0, %%g2 - cas [%1], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b +1: lduw [%1], %%g5 + sub %%g5, %0, %%g7 + cas [%1], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b nop" : /* No outputs */ : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); } /* Same as above, but return the result value. */ @@ -53,15 +53,15 @@ { unsigned long oldval; __asm__ __volatile__(" -1: lduw [%2], %%g1 - add %%g1, %1, %%g2 - cas [%2], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b - add %%g2, %1, %0" +1: lduw [%2], %%g5 + add %%g5, %1, %%g7 + cas [%2], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b + add %%g7, %1, %0" : "=&r" (oldval) : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); return (int)oldval; } @@ -69,15 +69,15 @@ { unsigned long oldval; __asm__ __volatile__(" -1: lduw [%2], %%g1 - sub %%g1, %1, %%g2 - cas [%2], %%g1, %%g2 - sub %%g1, %%g2, %%g1 - brnz,pn %%g1, 1b - sub %%g2, %1, %0" +1: lduw [%2], %%g5 + sub %%g5, %1, %%g7 + cas [%2], %%g5, %%g7 + sub %%g5, %%g7, %%g5 + brnz,pn %%g5, 1b + sub %%g7, %1, %0" : "=&r" (oldval) : "HIr" (i), "r" (__atomic_fool_gcc(v)) - : "g1", "g2"); + : "g5", "g7", "memory"); return (int)oldval; } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h --- v2.1.50/linux/include/asm-sparc64/bitops.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/bitops.h Sat Aug 16 09:51:10 1997 @@ -1,7 +1,7 @@ -/* $Id: bitops.h,v 1.19 1997/07/08 10:17:37 davem Exp $ +/* $Id: bitops.h,v 1.22 1997/08/07 02:54:04 davem Exp $ * bitops.h: Bit string operations on the V9. * - * Copyright 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) */ #ifndef _SPARC64_BITOPS_H @@ -21,84 +21,117 @@ extern __inline__ unsigned long test_and_set_bit(unsigned long nr, void *addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + unsigned long oldbit; __asm__ __volatile__(" - ldx [%4], %0 -1: - andcc %0, %3, %2 +1: ldx [%2], %%g7 + andcc %%g7, %1, %0 bne,pn %%xcc, 2f - xor %0, %3, %1 - casx [%4], %0, %1 - cmp %0, %1 - bne,a,pn %%xcc, 1b - ldx [%4], %0 + xor %%g7, %1, %%g5 + casx [%2], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 63)), "r" (m) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ void set_bit(unsigned long nr, void *addr) { - (void) test_and_set_bit(nr, addr); + unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + + __asm__ __volatile__(" +1: ldx [%1], %%g7 + andcc %%g7, %0, %%g0 + bne,pn %%xcc, 2f + xor %%g7, %0, %%g5 + casx [%1], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +2: +" : /* no outputs */ + : "HIr" (1UL << (nr & 63)), "r" (m) + : "g5", "g7", "cc", "memory"); } extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, void *addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + unsigned long oldbit; __asm__ __volatile__(" - ldx [%4], %0 -1: - andcc %0, %3, %2 +1: ldx [%2], %%g7 + andcc %%g7, %1, %0 be,pn %%xcc, 2f - xor %0, %3, %1 - casx [%4], %0, %1 - cmp %0, %1 - bne,a,pn %%xcc, 1b - ldx [%4], %0 + xor %%g7, %1, %%g5 + casx [%2], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 63)), "r" (m) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ void clear_bit(unsigned long nr, void *addr) { - (void) test_and_clear_bit(nr, addr); + unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + + __asm__ __volatile__(" +1: ldx [%1], %%g7 + andcc %%g7, %0, %%g0 + be,pn %%xcc, 2f + xor %%g7, %0, %%g5 + casx [%1], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +2: +" : /* no outputs */ + : "HIr" (1UL << (nr & 63)), "r" (m) + : "g5", "g7", "cc", "memory"); } extern __inline__ unsigned long test_and_change_bit(unsigned long nr, void *addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + unsigned long oldbit; __asm__ __volatile__(" - ldx [%4], %0 -1: - and %0, %3, %2 - xor %0, %3, %1 - casx [%4], %0, %1 - cmp %0, %1 - bne,a,pn %%xcc, 1b - ldx [%4], %0 -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +1: ldx [%2], %%g7 + and %%g7, %1, %0 + xor %%g7, %1, %%g5 + casx [%2], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 63)), "r" (m) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ void change_bit(unsigned long nr, void *addr) { - (void) test_and_change_bit(nr, addr); + unsigned long * m = ((unsigned long *) addr) + (nr >> 6); + + __asm__ __volatile__(" +1: ldx [%1], %%g7 + xor %%g7, %0, %%g5 + casx [%1], %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%xcc, 1b + nop +" : /* no outputs */ + : "HIr" (1UL << (nr & 63)), "r" (m) + : "g5", "g7", "cc", "memory"); } extern __inline__ unsigned long test_bit(int nr, __const__ void *addr) @@ -201,47 +234,43 @@ */ extern __inline__ int set_le_bit(int nr,void * addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned int * m = ((unsigned int *) addr) + (nr >> 5); + unsigned long oldbit; __asm__ __volatile__(" - lduwa [%4] %5, %0 -1: - andcc %0, %3, %2 +1: lduwa [%2] %3, %%g7 + andcc %%g7, %1, %0 bne,pn %%icc, 2f - xor %0, %3, %1 - casa [%4] %5, %0, %1 - cmp %0, %1 - bne,a,pn %%icc, 1b - lduwa [%4] %5, %0 + xor %%g7, %1, %%g5 + casa [%2] %3, %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%icc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 31)), "r" (m), "i" (ASI_PL) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } extern __inline__ int clear_le_bit(int nr, void * addr) { - unsigned long oldbit; - unsigned long temp0, temp1; unsigned int * m = ((unsigned int *) addr) + (nr >> 5); + unsigned long oldbit; __asm__ __volatile__(" - lduwa [%4] %5, %0 -1: - andcc %0, %3, %2 +1: lduwa [%2] %3, %%g7 + andcc %%g7, %1, %0 be,pn %%icc, 2f - xor %0, %3, %1 - casa [%4] %5, %0, %1 - cmp %0, %1 - bne,a,pn %%icc, 1b - lduwa [%4] %5, %0 + xor %%g7, %1, %%g5 + casa [%2] %3, %%g7, %%g5 + cmp %%g7, %%g5 + bne,pn %%icc, 1b + nop 2: -" : "=&r" (temp0), "=&r" (temp1), "=&r" (oldbit) +" : "=&r" (oldbit) : "HIr" (1UL << (nr & 31)), "r" (m), "i" (ASI_PL) - : "cc"); + : "g5", "g7", "cc", "memory"); return oldbit != 0; } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/checksum.h linux/include/asm-sparc64/checksum.h --- v2.1.50/linux/include/asm-sparc64/checksum.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/checksum.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: checksum.h,v 1.9 1997/06/26 04:05:17 davem Exp $ */ +/* $Id: checksum.h,v 1.10 1997/08/09 18:09:03 jj Exp $ */ #ifndef __SPARC64_CHECKSUM_H #define __SPARC64_CHECKSUM_H @@ -42,47 +42,25 @@ csum_partial_copy_nocheck(src,dst,len,sum) #define csum_partial_copy_fromuser(s, d, l, w) \ csum_partial_copy_from_user((char *) (s), (d), (l), (w), NULL) + +extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, int len, unsigned int sum); extern __inline__ unsigned int csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum) { - register unsigned long ret asm("o0") = (unsigned long)src; - register char *d asm("o1") = dst; - register unsigned long l asm("g1") = len; - - __asm__ __volatile__ (" - wr %%g0, %5, %%asi - call __csum_partial_copy_sparc_generic - mov %4, %%g7 - srl %%o0, 0, %%o0 - " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (sum), "i" (ASI_P) : - "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g5", "g7"); - return (unsigned int)ret; + __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_P)); + return csum_partial_copy_sparc64(src, dst, len, sum); } extern __inline__ unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *err) { - register unsigned long ret asm("o0") = (unsigned long)src; - register char *d asm("o1") = dst; - register unsigned long l asm("g1") = len; - register unsigned long s asm("g7") = sum; - - __asm__ __volatile__ (" - .section __ex_table,#alloc - .align 8 - .xword 1f,2 - .previous - wr %%g0, %6, %%asi -1: - call __csum_partial_copy_sparc_generic - stx %5, [%%sp + 0x7ff + 128] - srl %%o0, 0, %%o0 - " : "=r" (ret) : "0" (ret), "r" (d), "r" (l), "r" (s), "r" (err), "i" (ASI_S) : - "o1", "o2", "o3", "o4", "o5", "o7", "g1", "g2", "g3", "g5", "g7"); - return (unsigned int)ret; + __asm__ __volatile__ ("wr %%g0, %0, %%asi + stx %1, [%%sp + 0x7ff + 128] + " : : "i" (ASI_S), "r" (err)); + return csum_partial_copy_sparc64(src, dst, len, sum); } #if 0 diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/delay.h linux/include/asm-sparc64/delay.h --- v2.1.50/linux/include/asm-sparc64/delay.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/delay.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: delay.h,v 1.5 1997/06/18 12:36:23 jj Exp $ +/* $Id: delay.h,v 1.6 1997/07/29 21:11:22 davem Exp $ * delay.h: Linux delay routines on the V9. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu). @@ -7,7 +7,9 @@ #ifndef __SPARC64_DELAY_H #define __SPARC64_DELAY_H -extern unsigned long loops_per_sec; +#ifdef __SMP__ +#include +#endif extern __inline__ void __delay(unsigned long loops) { @@ -23,7 +25,7 @@ : "cc"); } -extern __inline__ void udelay(unsigned long usecs) +extern __inline__ void __udelay(unsigned long usecs, unsigned long lps) { usecs *= 0x00000000000010c6UL; /* 2**32 / 1000000 */ @@ -31,10 +33,18 @@ mulx %1, %2, %0 srlx %0, 32, %0 " : "=r" (usecs) - : "r" (usecs), "r" (loops_per_sec)); + : "r" (usecs), "r" (lps)); __delay(usecs); } + +#ifdef __SMP__ +#define __udelay_val cpu_data[smp_processor_id()].udelay_val +#else +#define __udelay_val loops_per_sec +#endif + +#define udelay(usecs) __udelay((usecs),__udelay_val) extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) { diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h --- v2.1.50/linux/include/asm-sparc64/ebus.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/ebus.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,51 @@ +/* $Id: ebus.h,v 1.1 1997/08/12 04:13:12 ecd Exp $ + * ebus.h: PCI to Ebus pseudo driver software state. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef __SPARC64_EBUS_H +#define __SPARC64_EBUS_H + +#include + +struct linux_ebus_device { + struct linux_ebus_device *next; + struct linux_ebus *parent; + int prom_node; + char prom_name[64]; + struct linux_prom_registers regs[PROMREG_MAX]; + int num_registers; + struct linux_prom_irqs irqs[PROMINTR_MAX]; + int num_irqs; +}; + +struct linux_ebus { + struct linux_ebus *next; + struct linux_ebus_device *devices; + struct linux_pbm_info *parent; + int prom_node; + char prom_name[64]; + struct linux_prom_ranges ebus_ranges[PROMREG_MAX]; + int num_ebus_ranges; +}; + +extern struct linux_ebus *ebus_chain; + +extern unsigned long ebus_init(unsigned long, unsigned long); +extern void prom_apply_ebus_ranges(struct linux_ebus *ebus, + struct linux_prom_registers *regs, + int nregs); + +#define for_each_ebus(bus) \ + for((bus) = ebus_chain; (bus); (bus) = (bus)->next) + +#define for_each_ebusdev(dev, bus) \ + for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) + +#define for_all_ebusdev(dev, bus) \ + for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0); \ + (bus); ((dev) = (dev)->next ? (dev)->next : \ + ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) + +#endif /* !(__SPARC64_EBUS_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/fhc.h linux/include/asm-sparc64/fhc.h --- v2.1.50/linux/include/asm-sparc64/fhc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/fhc.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,45 @@ +/* $Id: fhc.h,v 1.1 1997/08/08 04:26:40 davem Exp $ + * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire. + * + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC64_FHC_H +#define _SPARC64_FHC_H + +#include +#include + +struct linux_fhc; + +struct linux_central { + struct linux_fhc *child; + int prom_node; + char prom_name[64]; + + struct linux_prom_ranges central_ranges[PROMREG_MAX]; + int num_central_ranges; +}; + +struct linux_fhc { + struct linux_fhc *next; + struct linux_central *parent; /* NULL if not central FHC */ + struct fhc_regs fhc_regs; + int prom_node; + char prom_name[64]; + + struct linux_prom_ranges fhc_ranges[PROMREG_MAX]; + int num_fhc_ranges; +}; + +extern struct linux_central *central_bus; + +extern void prom_apply_central_ranges(struct linux_central *central, + struct linux_prom_registers *regs, + int nregs); + +extern void prom_apply_fhc_ranges(struct linux_fhc *fhc, + struct linux_prom_registers *regs, + int nregs); + +#endif /* !(_SPARC64_FHC_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/firehose.h linux/include/asm-sparc64/firehose.h --- v2.1.50/linux/include/asm-sparc64/firehose.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/firehose.h Sat Aug 16 09:51:10 1997 @@ -1,6 +1,6 @@ -/* $Id: firehose.h,v 1.1 1997/04/11 02:38:47 davem Exp $ +/* $Id: firehose.h,v 1.2 1997/08/08 04:26:31 davem Exp $ * firehose.h: Defines for the Fire Hose Controller (FHC) found - * on Sunfire/Wildfire systems. + * on Sunfire/Starfire/Wildfire systems. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ @@ -33,38 +33,38 @@ * for the FHC, thus we have the following few structs... */ struct fhc_ign_reg { -/*0x2000*/ u64 fhc_ign; /* FHC Interrupt Group Number */ +/*0x2000*/ u64 fhc_ign; /* FHC Interrupt Group Number */ }; struct fhc_fanfail_regs { -/*0x4000*/ u64 fhc_ff_imap; /* FHC FanFail Interrupt Map */ - u64 _unused1; -/*0x4010*/ u64 fhc_ff_istate; /* FHC FanFail Interrupt State */ +/*0x4000*/ u32 _pad0, fhc_ff_imap; /* FHC FanFail Interrupt Map */ + u64 _pad1; +/*0x4010*/ u32 _pad2, fhc_ff_iclr; /* FHC FanFail Interrupt Clear */ }; struct fhc_system_regs { -/*0x6000*/ u64 fhc_sys_imap; /* FHC System Interrupt Map */ - u64 _unused1; -/*0x6010*/ u64 fhc_sys_istate; /* FHC System Interrupt State */ +/*0x6000*/ u32 _pad0, fhc_sys_imap; /* FHC System Interrupt Map */ + u64 _pad1; +/*0x6010*/ u32 _pad2, fhc_sys_iclr; /* FHC System Interrupt Clear */ }; struct fhc_uart_regs { -/*0x8000*/ u64 fhc_uart_imap; /* FHC UART Interrupt Map */ - u64 _unused1; -/*0x8010*/ u64 fhc_uart_istate;/* FHC UART Interrupt State */ +/*0x8000*/ u32 _pad0, fhc_uart_imap; /* FHC UART Interrupt Map */ + u64 _pad1; +/*0x8010*/ u32 _pad2, fhc_uart_iclr; /* FHC UART Interrupt Clear */ }; struct fhc_tod_regs { -/*0xa000*/ u64 fhc_tod_imap; /* FHC TOD Interrupt Map */ - u64 _unused1; -/*0xa010*/ u64 fhc_tod_istate; /* FHC TOD Interrupt State */ +/*0xa000*/ u32 _pad0, fhc_tod_imap; /* FHC TOD Interrupt Map */ + u64 _pad1; +/*0xa010*/ u32 _pad2, fhc_tod_iclr; /* FHC TOD Interrupt Clear */ }; /* All of the above. */ struct fhc_regs { struct fhc_internal_regs *pregs; struct fhc_ign_reg *ireg; - struct fhc_fanfil_regs *ffregs; + struct fhc_fanfail_regs *ffregs; struct fhc_system_regs *sregs; struct fhc_uart_regs *uregs; struct fhc_tod_regs *tregs; diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/hardirq.h linux/include/asm-sparc64/hardirq.h --- v2.1.50/linux/include/asm-sparc64/hardirq.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/hardirq.h Sat Aug 16 09:51:10 1997 @@ -8,16 +8,20 @@ #include -extern unsigned int local_irq_count[NR_CPUS]; -#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) +#ifndef __SMP__ +extern unsigned int local_irq_count; +#else +#define local_irq_count (cpu_data[smp_processor_id()].irq_count) +#endif +#define in_interrupt() (local_irq_count != 0) #ifndef __SMP__ -#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_trylock(cpu) (local_irq_count == 0) #define hardirq_endlock(cpu) do { } while(0) -#define hardirq_enter(cpu) (local_irq_count[cpu]++) -#define hardirq_exit(cpu) (local_irq_count[cpu]--) +#define hardirq_enter(cpu) (local_irq_count++) +#define hardirq_exit(cpu) (local_irq_count--) #define synchronize_irq() do { } while(0) @@ -43,14 +47,16 @@ static inline void hardirq_enter(int cpu) { - ++local_irq_count[cpu]; + ++cpu_data[cpu].irq_count; atomic_inc(&global_irq_count); + membar("#StoreLoad | #StoreStore"); } static inline void hardirq_exit(int cpu) { + membar("#StoreStore | #LoadStore"); atomic_dec(&global_irq_count); - --local_irq_count[cpu]; + --cpu_data[cpu].irq_count; } static inline int hardirq_trylock(int cpu) @@ -58,13 +64,14 @@ unsigned long flags; __save_and_cli(flags); - if(atomic_add_return(1, &global_irq_count) != 1 || - *(((unsigned char *)(&global_irq_lock)))) { + atomic_inc(&global_irq_count); + if(atomic_read(&global_irq_count) != 1 || + (*(((unsigned char *)(&global_irq_lock)))) != 0) { atomic_dec(&global_irq_count); __restore_flags(flags); return 0; } - ++local_irq_count[cpu]; + ++cpu_data[cpu].irq_count; return 1; } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/head.h linux/include/asm-sparc64/head.h --- v2.1.50/linux/include/asm-sparc64/head.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/head.h Sat Aug 16 09:51:10 1997 @@ -1,324 +1,9 @@ -/* $Id: head.h,v 1.27 1997/07/13 17:30:43 davem Exp $ */ +/* $Id: head.h,v 1.30 1997/08/08 08:34:33 jj Exp $ */ #ifndef _SPARC64_HEAD_H #define _SPARC64_HEAD_H #include #define KERNBASE 0x400000 -#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop; - -/* We need a "cleaned" instruction... */ -#define CLEAN_WINDOW \ - rdpr %cleanwin, %l0; add %l0, 1, %l0; \ - wrpr %l0, 0x0, %cleanwin; \ - clr %o0; clr %o1; clr %o2; clr %o3; \ - clr %o4; clr %o5; clr %o6; clr %o7; \ - clr %l0; clr %l1; clr %l2; clr %l3; \ - clr %l4; clr %l5; clr %l6; clr %l7; \ - retry; \ - nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; - -#define TRAP(routine) \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; \ - nop; - -#define TRAP_NOSAVE(routine) \ - ba,pt %xcc, routine; \ - nop; \ - nop; nop; nop; nop; nop; nop; - -#define TRAPTL1(routine) \ - ba,pt %xcc, etraptl1; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; \ - nop; - -#define TRAP_ARG(routine, arg) \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - call routine; \ - mov arg, %o1; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; - -#define TRAPTL1_ARG(routine, arg) \ - ba,pt %xcc, etraptl1; \ - rd %pc, %g7; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - call routine; \ - mov arg, %o1; \ - ba,pt %xcc, rtrap; \ - clr %l6; \ - nop; - -#define SYSCALL_TRAP(routine, systbl) \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - sethi %hi(systbl), %l7; \ - call routine; \ - or %l7, %lo(systbl), %l7; \ - nop; nop; nop; - -#define ACCESS_EXCEPTION_TRAP(routine) \ - rdpr %pstate, %g1; \ - wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; - -#define ACCESS_EXCEPTION_TRAPTL1(routine) \ - rdpr %pstate, %g1; \ - wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ - ba,pt %xcc, etraptl1; \ - rd %pc, %g7; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ - ba,pt %xcc, rtrap; \ - clr %l6; - -#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sunos_sys_table) -#define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table32) -#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64) -#define GETCC_TRAP TRAP(getcc) -#define SETCC_TRAP TRAP(setcc) -/* FIXME: Write these actually */ -#define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall) -#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall) -#define BREAKPOINT_TRAP TRAP(breakpoint_trap) -#define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl) - -#define TRAP_IRQ(routine, level) \ - rdpr %pil, %g2; \ - wrpr %g0, 15, %pil; \ - ba,pt %xcc, etrap_irq; \ - rd %pc, %g7; \ - mov level, %o0; \ - call routine; \ - add %sp, STACK_BIAS + REGWIN_SZ, %o1; \ - ba,a,pt %xcc, rtrap_clr_l6; - -/* On UP this is ok, and worth the effort, for SMP we need - * a different mechanism and thus cannot do it all in trap table. -DaveM - */ -#ifndef __SMP__ -#define TRAP_IVEC \ - ldxa [%g2] ASI_UDB_INTR_R, %g3; \ - and %g3, 0x7ff, %g3; \ - sllx %g3, 3, %g3; \ - ldx [%g1 + %g3], %g5; \ - wr %g5, 0x0, %set_softint; \ - stxa %g0, [%g0] ASI_INTR_RECEIVE; \ - membar #Sync; \ - retry; -#else -#define TRAP_IVEC TRAP_NOSAVE(do_ivec) -#endif - -#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl) - -#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl) - -#define FLUSH_WINDOW_TRAP \ - ba,pt %xcc, etrap; \ - rd %pc, %g7; \ - flushw; \ - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1; \ - add %l1, 4, %l2; \ - stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]; \ - ba,pt %xcc, rtrap_clr_l6; \ - stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]; - -/* Before touching these macros, you owe it to yourself to go and - * see how arch/sparc64/kernel/winfixup.S works... -DaveM - */ - -/* Normal kernel spill */ -#define SPILL_0_NORMAL \ - stx %l0, [%sp + STACK_BIAS + 0x00]; \ - stx %l1, [%sp + STACK_BIAS + 0x08]; \ - stx %l2, [%sp + STACK_BIAS + 0x10]; \ - stx %l3, [%sp + STACK_BIAS + 0x18]; \ - stx %l4, [%sp + STACK_BIAS + 0x20]; \ - stx %l5, [%sp + STACK_BIAS + 0x28]; \ - stx %l6, [%sp + STACK_BIAS + 0x30]; \ - stx %l7, [%sp + STACK_BIAS + 0x38]; \ - stx %i0, [%sp + STACK_BIAS + 0x40]; \ - stx %i1, [%sp + STACK_BIAS + 0x48]; \ - stx %i2, [%sp + STACK_BIAS + 0x50]; \ - stx %i3, [%sp + STACK_BIAS + 0x58]; \ - stx %i4, [%sp + STACK_BIAS + 0x60]; \ - stx %i5, [%sp + STACK_BIAS + 0x68]; \ - stx %i6, [%sp + STACK_BIAS + 0x70]; \ - stx %i7, [%sp + STACK_BIAS + 0x78]; \ - saved; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; nop; nop; - -/* Normal 64bit spill */ -#define SPILL_1_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - stxa %l0, [%sp + STACK_BIAS + 0x00] %asi; \ - stxa %l1, [%sp + STACK_BIAS + 0x08] %asi; \ - stxa %l2, [%sp + STACK_BIAS + 0x10] %asi; \ - stxa %l3, [%sp + STACK_BIAS + 0x18] %asi; \ - stxa %l4, [%sp + STACK_BIAS + 0x20] %asi; \ - stxa %l5, [%sp + STACK_BIAS + 0x28] %asi; \ - stxa %l6, [%sp + STACK_BIAS + 0x30] %asi; \ - stxa %l7, [%sp + STACK_BIAS + 0x38] %asi; \ - stxa %i0, [%sp + STACK_BIAS + 0x40] %asi; \ - stxa %i1, [%sp + STACK_BIAS + 0x48] %asi; \ - stxa %i2, [%sp + STACK_BIAS + 0x50] %asi; \ - stxa %i3, [%sp + STACK_BIAS + 0x58] %asi; \ - stxa %i4, [%sp + STACK_BIAS + 0x60] %asi; \ - stxa %i5, [%sp + STACK_BIAS + 0x68] %asi; \ - stxa %i6, [%sp + STACK_BIAS + 0x70] %asi; \ - stxa %i7, [%sp + STACK_BIAS + 0x78] %asi; \ - saved; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; \ - b,a,pt %xcc, spill_fixup_mna; \ - b,a,pt %xcc, spill_fixup; - -/* Normal 32bit spill */ -#define SPILL_2_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - srl %sp, 0, %sp; \ - stwa %l0, [%sp + 0x00] %asi; \ - stwa %l1, [%sp + 0x04] %asi; \ - stwa %l2, [%sp + 0x08] %asi; \ - stwa %l3, [%sp + 0x0c] %asi; \ - stwa %l4, [%sp + 0x10] %asi; \ - stwa %l5, [%sp + 0x14] %asi; \ - stwa %l6, [%sp + 0x18] %asi; \ - stwa %l7, [%sp + 0x1c] %asi; \ - stwa %i0, [%sp + 0x20] %asi; \ - stwa %i1, [%sp + 0x24] %asi; \ - stwa %i2, [%sp + 0x28] %asi; \ - stwa %i3, [%sp + 0x2c] %asi; \ - stwa %i4, [%sp + 0x30] %asi; \ - stwa %i5, [%sp + 0x34] %asi; \ - stwa %i6, [%sp + 0x38] %asi; \ - stwa %i7, [%sp + 0x3c] %asi; \ - saved; retry; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; \ - b,a,pt %xcc, spill_fixup_mna; \ - b,a,pt %xcc, spill_fixup; - -#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP) -#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP) -#define SPILL_3_NORMAL SPILL_0_NORMAL -#define SPILL_4_NORMAL SPILL_0_NORMAL -#define SPILL_5_NORMAL SPILL_0_NORMAL -#define SPILL_6_NORMAL SPILL_0_NORMAL -#define SPILL_7_NORMAL SPILL_0_NORMAL - -#define SPILL_0_OTHER SPILL_0_NORMAL -#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS) -#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS) -#define SPILL_3_OTHER SPILL_3_NORMAL -#define SPILL_4_OTHER SPILL_4_NORMAL -#define SPILL_5_OTHER SPILL_5_NORMAL -#define SPILL_6_OTHER SPILL_6_NORMAL -#define SPILL_7_OTHER SPILL_7_NORMAL - -/* Normal kernel fill */ -#define FILL_0_NORMAL \ - ldx [%sp + STACK_BIAS + 0x00], %l0; \ - ldx [%sp + STACK_BIAS + 0x08], %l1; \ - ldx [%sp + STACK_BIAS + 0x10], %l2; \ - ldx [%sp + STACK_BIAS + 0x18], %l3; \ - ldx [%sp + STACK_BIAS + 0x20], %l4; \ - ldx [%sp + STACK_BIAS + 0x28], %l5; \ - ldx [%sp + STACK_BIAS + 0x30], %l6; \ - ldx [%sp + STACK_BIAS + 0x38], %l7; \ - ldx [%sp + STACK_BIAS + 0x40], %i0; \ - ldx [%sp + STACK_BIAS + 0x48], %i1; \ - ldx [%sp + STACK_BIAS + 0x50], %i2; \ - ldx [%sp + STACK_BIAS + 0x58], %i3; \ - ldx [%sp + STACK_BIAS + 0x60], %i4; \ - ldx [%sp + STACK_BIAS + 0x68], %i5; \ - ldx [%sp + STACK_BIAS + 0x70], %i6; \ - ldx [%sp + STACK_BIAS + 0x78], %i7; \ - restored; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; nop; nop; - -/* Normal 64bit fill */ -#define FILL_1_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - ldxa [%sp + STACK_BIAS + 0x00] %asi, %l0; \ - ldxa [%sp + STACK_BIAS + 0x08] %asi, %l1; \ - ldxa [%sp + STACK_BIAS + 0x10] %asi, %l2; \ - ldxa [%sp + STACK_BIAS + 0x18] %asi, %l3; \ - ldxa [%sp + STACK_BIAS + 0x20] %asi, %l4; \ - ldxa [%sp + STACK_BIAS + 0x28] %asi, %l5; \ - ldxa [%sp + STACK_BIAS + 0x30] %asi, %l6; \ - ldxa [%sp + STACK_BIAS + 0x38] %asi, %l7; \ - ldxa [%sp + STACK_BIAS + 0x40] %asi, %i0; \ - ldxa [%sp + STACK_BIAS + 0x48] %asi, %i1; \ - ldxa [%sp + STACK_BIAS + 0x50] %asi, %i2; \ - ldxa [%sp + STACK_BIAS + 0x58] %asi, %i3; \ - ldxa [%sp + STACK_BIAS + 0x60] %asi, %i4; \ - ldxa [%sp + STACK_BIAS + 0x68] %asi, %i5; \ - ldxa [%sp + STACK_BIAS + 0x70] %asi, %i6; \ - ldxa [%sp + STACK_BIAS + 0x78] %asi, %i7; \ - restored; retry; nop; nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; \ - b,a,pt %xcc, fill_fixup_mna; \ - b,a,pt %xcc, fill_fixup; - -/* Normal 32bit fill */ -#define FILL_2_GENERIC(xxx) \ - wr %g0, xxx, %asi; \ - srl %sp, 0, %sp; \ - lduwa [%sp + 0x00] %asi, %l0; \ - lduwa [%sp + 0x04] %asi, %l1; \ - lduwa [%sp + 0x08] %asi, %l2; \ - lduwa [%sp + 0x0c] %asi, %l3; \ - lduwa [%sp + 0x10] %asi, %l4; \ - lduwa [%sp + 0x14] %asi, %l5; \ - lduwa [%sp + 0x18] %asi, %l6; \ - lduwa [%sp + 0x1c] %asi, %l7; \ - lduwa [%sp + 0x20] %asi, %i0; \ - lduwa [%sp + 0x24] %asi, %i1; \ - lduwa [%sp + 0x28] %asi, %i2; \ - lduwa [%sp + 0x2c] %asi, %i3; \ - lduwa [%sp + 0x30] %asi, %i4; \ - lduwa [%sp + 0x34] %asi, %i5; \ - lduwa [%sp + 0x38] %asi, %i6; \ - lduwa [%sp + 0x3c] %asi, %i7; \ - restored; retry; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; nop; \ - b,a,pt %xcc, fill_fixup_mna; \ - b,a,pt %xcc, fill_fixup; - -#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP) -#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP) -#define FILL_3_NORMAL FILL_0_NORMAL -#define FILL_4_NORMAL FILL_0_NORMAL -#define FILL_5_NORMAL FILL_0_NORMAL -#define FILL_6_NORMAL FILL_0_NORMAL -#define FILL_7_NORMAL FILL_0_NORMAL - -#define FILL_0_OTHER FILL_0_NORMAL -#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS) -#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS) -#define FILL_3_OTHER FILL_3_NORMAL -#define FILL_4_OTHER FILL_4_NORMAL -#define FILL_5_OTHER FILL_5_NORMAL -#define FILL_6_OTHER FILL_6_NORMAL -#define FILL_7_OTHER FILL_7_NORMAL #endif /* !(_SPARC64_HEAD_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/ioctls.h linux/include/asm-sparc64/ioctls.h --- v2.1.50/linux/include/asm-sparc64/ioctls.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/ioctls.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: ioctls.h,v 1.4 1997/06/23 07:26:03 davem Exp $ */ +/* $Id: ioctls.h,v 1.5 1997/08/12 04:13:13 ecd Exp $ */ #ifndef _ASM_SPARC64_IOCTLS_H #define _ASM_SPARC64_IOCTLS_H @@ -105,6 +105,8 @@ #define TIOCSERGETLSR 0x5459 /* Get line status register */ #define TIOCSERGETMULTI 0x545A /* Get multiport config */ #define TIOCSERSETMULTI 0x545B /* Set multiport config */ +#define TIOCMIWAIT 0x545C /* Wait for change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ /* Kernel definitions */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/iommu.h linux/include/asm-sparc64/iommu.h --- v2.1.50/linux/include/asm-sparc64/iommu.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/iommu.h Sat Aug 16 09:51:10 1997 @@ -7,6 +7,7 @@ #include #include +#include /* The iommu handles all virtual to physical address translations * that occur between the SYSIO and physical memory. Access by @@ -43,8 +44,12 @@ #define IOPTE_WRITE 0x0000000000000002 /* Writeable */ struct iommu_struct { - struct sysio_regs *sysio_regs; - iopte_t *page_table; + struct sysio_regs *sysio_regs; + unsigned int *sbuf_flushflag_va; + unsigned long sbuf_flushflag_pa; + spinlock_t iommu_lock; + + iopte_t *page_table; /* For convenience */ unsigned long start; /* First managed virtual address */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h --- v2.1.50/linux/include/asm-sparc64/irq.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/irq.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: irq.h,v 1.4 1997/04/04 00:50:20 davem Exp $ +/* $Id: irq.h,v 1.6 1997/08/07 08:06:40 davem Exp $ * irq.h: IRQ registers on the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -9,7 +9,31 @@ #include -#include /* For NCPUS */ +/* Sparc64 extensions to the interrupt registry flags. Mostly this is + * for passing along what bus type the device is on and also the true + * format of the dev_id cookie, see below. + */ +#define SA_BUSMASK 0x0f000 +#define SA_SBUS 0x01000 +#define SA_PCI 0x02000 +#define SA_FHC 0x03000 +#define SA_EBUS 0x04000 +#define SA_BUS(mask) ((mask) & SA_BUSMASK) + +struct devid_cookie { + /* Caller specifies these. */ + void *real_dev_id; /* What dev_id would usually contain. */ + unsigned int *imap; /* Anonymous IMAP register */ + unsigned int *iclr; /* Anonymous ICLR register */ + int pil; /* Anonymous PIL */ + void *bus_cookie; /* SYSIO regs, PSYCHO regs, etc. */ + + /* Return values. */ + unsigned int ret_ino; + unsigned int ret_pil; +}; + +#define SA_DCOOKIE 0x10000 #define NR_IRQS 15 diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h --- v2.1.50/linux/include/asm-sparc64/mmu_context.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/mmu_context.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: mmu_context.h,v 1.17 1997/07/13 19:13:39 davem Exp $ */ +/* $Id: mmu_context.h,v 1.19 1997/08/07 02:54:08 davem Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H @@ -11,20 +11,33 @@ #ifndef __ASSEMBLY__ -#define destroy_context(mm) do { } while(0) - extern unsigned long tlb_context_cache; #define CTX_VERSION_SHIFT PAGE_SHIFT #define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) #define CTX_FIRST_VERSION ((1UL << CTX_VERSION_SHIFT) + 1UL) -extern void get_new_mmu_context(struct mm_struct *mm, unsigned long ctx); +extern void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx); -/* Initialize the context related info for a new mm_struct +/* Initialize/destroy the context related info for a new mm_struct * instance. */ -#define init_new_context(mm) get_new_mmu_context((mm), tlb_context_cache) +#define init_new_context(mm) ((mm)->context = NO_CONTEXT) +#define destroy_context(mm) ((mm)->context = NO_CONTEXT) + +#ifdef __SMP__ +#define LOCAL_FLUSH_PENDING(cpu) \ + ((cpu_data[(cpu)].last_tlbversion_seen ^ tlb_context_cache) & CTX_VERSION_MASK) +#define DO_LOCAL_FLUSH(cpu) do { __flush_tlb_all(); \ + cpu_data[cpu].last_tlbversion_seen = \ + tlb_context_cache & CTX_VERSION_MASK; \ + } while(0) +#else +#define LOCAL_FLUSH_PENDING(cpu) 0 +#define DO_LOCAL_FLUSH(cpu) do { __flush_tlb_all(); } while(0) +#endif + +extern void __flush_tlb_all(void); extern __inline__ void get_mmu_context(struct task_struct *tsk) { @@ -32,11 +45,13 @@ struct mm_struct *mm = tsk->mm; flushw_user(); + if(LOCAL_FLUSH_PENDING(current->processor)) + DO_LOCAL_FLUSH(current->processor); if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD) && !(tsk->flags & PF_EXITING)) { unsigned long ctx = tlb_context_cache; if((mm->context ^ ctx) & CTX_VERSION_MASK) - get_new_mmu_context(mm, ctx); + get_new_mmu_context(mm, &tlb_context_cache); /* Don't worry, set_fs() will restore it... */ tsk->tss.ctx = (tsk->tss.current_ds ? diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/openprom.h linux/include/asm-sparc64/openprom.h --- v2.1.50/linux/include/asm-sparc64/openprom.h Mon Apr 14 16:28:23 1997 +++ linux/include/asm-sparc64/openprom.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: openprom.h,v 1.4 1997/03/24 06:42:08 davem Exp $ */ +/* $Id: openprom.h,v 1.5 1997/08/15 06:44:51 davem Exp $ */ #ifndef __SPARC64_OPENPROM_H #define __SPARC64_OPENPROM_H @@ -208,6 +208,28 @@ unsigned int ot_parent_space; unsigned int ot_parent_base; /* CPU looks from here */ unsigned int or_size; +}; + +/* Ranges and reg properties are a bit different for PCI. */ +struct linux_prom_pci_registers { + unsigned int phys_hi; + unsigned int phys_mid; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_ranges { + unsigned int child_phys_hi; /* Only certain bits are encoded here. */ + unsigned int child_phys_mid; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_lo; + + unsigned int size_hi; + unsigned int size_lo; }; #endif /* !(__ASSEMBLY__) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h --- v2.1.50/linux/include/asm-sparc64/page.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-sparc64/page.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.14 1997/06/26 22:32:03 davem Exp $ */ +/* $Id: page.h,v 1.15 1997/08/09 04:56:54 davem Exp $ */ #ifndef _SPARC64_PAGE_H #define _SPARC64_PAGE_H @@ -82,13 +82,11 @@ #endif /* (STRICT_MM_TYPECHECKS) */ -#endif /* !(__ASSEMBLY__) */ +#define TASK_UNMAPPED_BASE ((current->tss.flags & SPARC_FLAG_32BIT) ? \ + (0x0000000070000000UL) : \ + (0x0000030000000000UL)) -#ifndef __ASSEMBLY__ -#define TASK_UNMAPPED_BASE 0x0000000070000000UL -#else -#define TASK_UNMAPPED_BASE 0x0000000070000000 -#endif +#endif /* !(__ASSEMBLY__) */ /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h --- v2.1.50/linux/include/asm-sparc64/pbm.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/pbm.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,46 @@ +/* $Id: pbm.h,v 1.4 1997/08/15 06:44:52 davem Exp $ + * pbm.h: U2P PCI bus module pseudo driver software state. + * + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __SPARC64_PBM_H +#define __SPARC64_PBM_H + +#include +#include + +#include +#include + +struct linux_psycho; + +struct linux_pbm_info { + struct linux_psycho *parent; + unsigned long *pbm_IO; + unsigned long *pbm_mem; + int prom_node; + char prom_name[64]; + struct linux_prom_pci_ranges pbm_ranges[PROMREG_MAX]; + int num_pbm_ranges; + + /* Now things for the actual PCI bus probes. */ + unsigned int pci_first_busno; + unsigned int pci_last_busno; + struct pci_bus pci_bus; +}; + +struct linux_psycho { + struct linux_psycho *next; + struct psycho_regs *psycho_regs; + unsigned long *pci_config_space; + unsigned long *pci_IO_space; + unsigned long *pci_mem_space; + u32 upa_portid; + struct linux_pbm_info pbm_A; + struct linux_pbm_info pbm_B; +}; + +extern struct linux_psycho *psycho_root; + +#endif /* !(__SPARC64_PBM_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h --- v2.1.50/linux/include/asm-sparc64/pgtable.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/pgtable.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.50 1997/07/24 16:48:31 davem Exp $ +/* $Id: pgtable.h,v 1.57 1997/08/13 04:44:20 paulus Exp $ * pgtable.h: SpitFire page table operations. * * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -159,12 +159,13 @@ /* Cache and TLB flush operations. */ /* These are the same regardless of whether this is an SMP kernel or not. */ -#define flush_cache_mm(mm) do { } while(0) -#define flush_cache_range(mm, start, end) do { } while(0) -#define flush_cache_page(vma, page) do { } while(0) +#define flush_cache_mm(mm) flushw_user() +#define flush_cache_range(mm, start, end) flushw_user() +#define flush_cache_page(vma, page) flushw_user() /* This operation in unnecessary on the SpitFire since D-CACHE is write-through. */ #define flush_page_to_ram(page) do { } while (0) +#define flush_icache_range(start, end) do { } while (0) extern void __flush_cache_all(void); @@ -207,7 +208,7 @@ extern void smp_flush_tlb_mm(struct mm_struct *mm); extern void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); -extern void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); +extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page); #define flush_cache_all() smp_flush_cache_all() #define flush_tlb_all() smp_flush_tlb_all() @@ -230,7 +231,7 @@ struct mm_struct *mm = vma->vm_mm; if(mm->context != NO_CONTEXT) - smp_flush_tlb_page(vma, page); + smp_flush_tlb_page(mm, page & PAGE_MASK); } #endif @@ -259,18 +260,21 @@ extern inline unsigned long pgd_page(pgd_t pgd) { return (unsigned long) __va(pgd_val(pgd)); } +#define PMD_NONE_MAGIC 0x80 +#define PGD_NONE_MAGIC 0x40 + extern inline int pte_none(pte_t pte) { return !pte_val(pte); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } extern inline void pte_clear(pte_t *pte) { pte_val(*pte) = 0; } -extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd)==null_pte_table; } -extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK); } -extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd)!=null_pte_table; } +extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd)&PMD_NONE_MAGIC; } +extern inline int pmd_bad(pmd_t pmd) { return 0; } +extern inline int pmd_present(pmd_t pmd) { return !(pmd_val(pmd)&PMD_NONE_MAGIC);} extern inline void pmd_clear(pmd_t *pmdp) { pmd_val(*pmdp) = null_pte_table; } -extern inline int pgd_none(pgd_t pgd) { return pgd_val(pgd)==null_pmd_table; } -extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK); } -extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd)!=null_pmd_table; } +extern inline int pgd_none(pgd_t pgd) { return pgd_val(pgd) & PGD_NONE_MAGIC; } +extern inline int pgd_bad(pgd_t pgd) { return 0; } +extern inline int pgd_present(pgd_t pgd) { return !(pgd_val(pgd)&PGD_NONE_MAGIC);} extern inline void pgd_clear(pgd_t *pgdp) { pgd_val(*pgdp) = null_pmd_table; } /* The following only work if pte_present() is true. @@ -332,148 +336,127 @@ extern inline pte_t *pte_offset(pmd_t *dir, unsigned long address) { return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PAGE - 1)); } -extern __inline__ void __init_pmd(pmd_t *pmdp) +/* Very stupidly, we used to get new pgd's and pmd's, init their contents + * to point to the NULL versions of the next level page table, later on + * completely re-init them the same way, then free them up. This wasted + * a lot of work and caused unnecessary memory traffic. How broken... + * We fix this by caching them. + */ + +#ifdef __SMP__ +/* Sliiiicck */ +#define pgd_quicklist (cpu_data[smp_processor_id()].pgd_cache) +#define pmd_quicklist (cpu_data[smp_processor_id()].pmd_cache) +#define pte_quicklist (cpu_data[smp_processor_id()].pte_cache) +#define pgtable_cache_size (cpu_data[smp_processor_id()].pgcache_size) +#else +extern unsigned long *pgd_quicklist; +extern unsigned long *pmd_quicklist; +extern unsigned long *pte_quicklist; +extern unsigned long pgtable_cache_size; +#endif + +extern pgd_t *get_pgd_slow(void); + +extern __inline__ pgd_t *get_pgd_fast(void) { - extern void __bfill64(void *, unsigned long *); - - __bfill64((void *)pmdp, &null_pte_table); + pgd_t *ret; + + if((ret = (pgd_t *)pgd_quicklist) != NULL) { + pgd_quicklist = (unsigned long *)pgd_val(*ret); + pgd_val(ret[0]) = pgd_val(ret[1]); + (pgtable_cache_size)--; + } else + ret = get_pgd_slow(); + return ret; } -/* Turning this off makes things much faster, but eliminates some - * sanity checking as well. - */ -/* #define PGTABLE_SANITY_CHECKS */ +extern __inline__ void free_pgd_fast(pgd_t *pgd) +{ + pgd_val(*pgd) = (unsigned long) pgd_quicklist; + pgd_quicklist = (unsigned long *) pgd; + (pgtable_cache_size)++; +} -/* Allocate and free page tables. The xxx_kernel() versions are - * used to allocate a kernel page table - this turns on supervisor - * bits if any. - */ -extern inline void pte_free_kernel(pte_t *pte) -{ free_page((unsigned long)pte); } +extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked); -extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +extern __inline__ pmd_t *get_pmd_fast(void) { - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PTE); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, BAD_PTE); - return NULL; + pmd_t *ret; + + if((ret = (pmd_t *)pmd_quicklist) != NULL) { + pmd_quicklist = (unsigned long *)pmd_val(*ret); + pmd_val(ret[0]) = pmd_val(ret[1]); + (pgtable_cache_size)--; } -#endif - return (pte_t *) pmd_page(*pmd) + address; + return ret; } -extern inline void pmd_free_kernel(pmd_t *pmd) -{ free_page((unsigned long) pmd); } +extern __inline__ void free_pmd_fast(pgd_t *pmd) +{ + pmd_val(*pmd) = (unsigned long) pmd_quicklist; + pmd_quicklist = (unsigned long *) pmd; + (pgtable_cache_size)++; +} + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); -extern inline pmd_t * pmd_alloc_kernel(pgd_t *pgd, unsigned long address) +extern __inline__ pte_t *get_pte_fast(void) { - address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - __init_pmd(page); - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PMD); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pgd_bad(*pgd)) { - printk("Bad pgd in pmd_alloc_kernel: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, BAD_PMD); - return NULL; + pte_t *ret; + + if((ret = (pte_t *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)pte_val(*ret); + pte_val(ret[0]) = pte_val(ret[1]); + (pgtable_cache_size)--; } -#endif - return (pmd_t *) pgd_page(*pgd) + address; + return ret; } -extern inline void pte_free(pte_t * pte) -{ free_page((unsigned long)pte); } +extern __inline__ void free_pte_fast(pte_t *pte) +{ + pte_val(*pte) = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + (pgtable_cache_size)++; +} + +#define pte_free_kernel(pte) free_pte_fast(pte) +#define pte_free(pte) free_pte_fast(pte) +#define pmd_free_kernel(pmd) free_pmd_fast(pmd) +#define pmd_free(pmd) free_pmd_fast(pmd) +#define pgd_free(pgd) free_pgd_fast(pgd) +#define pgd_alloc() get_pgd_fast() extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address) { address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PTE); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pmd_bad(*pmd)) { - printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); - pmd_set(pmd, BAD_PTE); - return NULL; + pte_t *page = get_pte_fast(); + + if (!page) + return get_pte_slow(pmd, address); + pmd_set(pmd, page); + return page + address; } -#endif return (pte_t *) pmd_page(*pmd) + address; } -extern inline void pmd_free(pmd_t * pmd) -{ free_page((unsigned long) pmd); } - extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) { address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - __init_pmd(page); - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PMD); - return NULL; - } - free_page((unsigned long) page); - } -#ifdef PGTABLE_SANITY_CHECKS - if (pgd_bad(*pgd)) { - printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, BAD_PMD); - return NULL; + pmd_t *page = get_pmd_fast(); + + if (!page) + return get_pmd_slow(pgd, address); + pgd_set(pgd, page); + return page + address; } -#endif return (pmd_t *) pgd_page(*pgd) + address; } -extern inline void pgd_free(pgd_t * pgd) -{ free_page((unsigned long)pgd); } - -extern inline pgd_t * pgd_alloc(void) -{ - extern void __bfill64(void *, unsigned long *); - pgd_t *pgd = (pgd_t *) __get_free_page(GFP_KERNEL); - - if (pgd) - __bfill64((void *)pgd, &null_pmd_table); - return pgd; -} +#define pte_alloc_kernel(pmd, addr) pte_alloc(pmd, addr) +#define pmd_alloc_kernel(pgd, addr) pmd_alloc(pgd, addr) extern pgd_t swapper_pg_dir[1024]; @@ -505,22 +488,18 @@ extern __u32 mmu_get_scsi_one(char *, unsigned long, struct linux_sbus *sbus); extern void mmu_get_scsi_sgl(struct mmu_sglist *, int, struct linux_sbus *sbus); +extern void mmu_release_scsi_one(u32 vaddr, unsigned long len, + struct linux_sbus *sbus); +extern void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus); + +#define NEED_DMA_SYNCHRONIZATION +#define mmu_sync_dma(dma_addr, len, sbus_instance) \ + mmu_release_scsi_one((dma_addr), (len), (sbus_instance)) + /* These do nothing with the way I have things setup. */ -#define mmu_release_scsi_one(vaddr, len, sbus) do { } while(0) -#define mmu_release_scsi_sgl(sg, sz, sbus) do { } while(0) #define mmu_lockarea(vaddr, len) (vaddr) #define mmu_unlockarea(vaddr, len) do { } while(0) - -extern void fixup_dcache_alias(struct vm_area_struct *vma, unsigned long address, - pte_t pte); - -extern inline void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - /* Find and fix bad virutal cache aliases. */ - if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) - fixup_dcache_alias(vma, address, pte); -} +#define update_mmu_cache(vma, address, pte) do { } while(0) /* Make a non-present pseudo-TTE. */ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/psycho.h linux/include/asm-sparc64/psycho.h --- v2.1.50/linux/include/asm-sparc64/psycho.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/psycho.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,350 @@ +/* $Id: psycho.h,v 1.2 1997/08/11 14:35:40 davem Exp $ + * psycho.h: UltraSparc AX specific PCI definitions. + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef __SPARC64_PSYCHO_H +#define __SPARC64_PSYCHO_H + +#include + +/* Ultra AX PSYCHO Register Set, one per controller probed. */ +struct psycho_regs { +/*0x0000*/ u64 upa_id; /* PSYCHO UPA Port ID Register */ +/*0x0008*/ u64 upa_cfg; /* PSYCHO UPA Config Register */ +/*0x0010*/ u64 control; /* PSYCHO Control Register */ +/*0x0018*/ u64 __pad0; +/*0x0020*/ u64 ecc_control; /* ECC Control Register */ +/*0x0028*/ u64 __pad1; + + /* Uncorrectable Error Fault Registers */ +/*0x0030*/ u64 ue_afsr; /* UE Async Fault Status */ +/*0x0038*/ u64 ue_afar; /* UE Async Fault Address */ + + /* Correctable Error Fault Registers */ +/*0x0040*/ u64 ce_afsr; /* CE Async Fault Status */ +/*0x0048*/ u64 ce_afar; /* CE Async Fault Address */ + + u64 __pad2[0x16]; + + /* Performance Monitoring Registers */ +/*0x0100*/ u64 pmon_control; +/*0x0108*/ u64 pmon_counter; + + u64 __pad3[0x1e]; + + /* PCI Bus IOMMU lives here */ +/*0x0200*/ u64 iommu_control; /* IOMMU Control */ +/*0x0208*/ u64 iommu_tsbbase; /* IOMMU TSB Base */ +/*0x0210*/ u64 iommu_flush; /* IOMMU Flush Register */ + + u64 __pad4[0x13d]; + + /* Interrupt mapping/control registers */ +/*0x0c00*/ u64 imap_a_slot0; /* PCI A Slot 0 Int Mapping */ +/*0x0c08*/ u64 imap_a_slot1; /* PCI A Slot 1 Int Mapping */ + + u64 __pad5[0x2]; + +/*0x0c20*/ u64 imap_b_slot0; /* PCI B Slot 0 Int Mapping */ +/*0x0c28*/ u64 imap_b_slot1; /* PCI B Slot 1 Int Mapping */ +/*0x0c30*/ u64 imap_b_slot2; /* PCI B Slot 2 Int Mapping */ +/*0x0c38*/ u64 imap_b_slot3; /* PCI B Slot 3 Int Mapping */ + + u64 __pad6[0x78]; + +/*0x1000*/ u64 imap_scsi; /* SCSI Int Mapping */ +/*0x1008*/ u64 imap_eth; /* Ethernet Int Mapping */ +/*0x1010*/ u64 imap_bpp; /* Parallel Port Int Mapping */ +/*0x1018*/ u64 imap_au_rec; /* Audio Record Int Mapping */ +/*0x1020*/ u64 imap_au_play; /* Audio Playback Int Mapping */ +/*0x1028*/ u64 imap_pfail; /* Power Fail Int Mapping */ +/*0x1030*/ u64 imap_kms; /* Kbd/Mouse/Ser Int Mapping */ +/*0x1038*/ u64 imap_flpy; /* Floppy Int Mapping */ +/*0x1040*/ u64 imap_shw; /* Spare HW Int Mapping */ +/*0x1048*/ u64 imap_kbd; /* Kbd Only Int Mapping */ +/*0x1050*/ u64 imap_ms; /* Mouse Only Int Mapping */ +/*0x1058*/ u64 imap_ser; /* Serial Only Int Mapping */ +/*0x1060*/ u64 imap_tim0; /* Timer 0 Int Mapping */ +/*0x1068*/ u64 imap_tim1; /* Timer 1 Int Mapping */ +/*0x1070*/ u64 imap_ue; /* UE Int Mapping */ +/*0x1078*/ u64 imap_ce; /* CE Int Mapping */ +/*0x1080*/ u64 imap_a_err; /* PCI A Err Int Mapping */ +/*0x1088*/ u64 imap_b_err; /* PCI B Err Int Mapping */ +/*0x1090*/ u64 imap_pmgmt; /* Power Mgmt Int Mapping */ +/*0x1098*/ u64 imap_gfx; /* OB Graphics Int Mapping */ +/*0x10a0*/ u64 imap_eupa; /* UPA Expansion Int Mapping */ + + u64 __pad7[0x6b]; + + /* Interrupt Clear Registers */ +/*0x1400*/ u64 iclr_a_slot0[4]; /* PCI A Slot 0 Clear Int Reg */ +/*0x1420*/ u64 iclr_a_slot1[4]; /* PCI A Slot 1 Clear Int Reg */ + + u64 __pad8[0x8]; + +/*0x1480*/ u64 iclr_b_slot0[4]; /* PCI B Slot 0 Clear Int Reg */ +/*0x14a0*/ u64 iclr_b_slot1[4]; /* PCI B Slot 1 Clear Int Reg */ +/*0x14c0*/ u64 iclr_b_slot2[4]; /* PCI B Slot 2 Clear Int Reg */ +/*0x14e0*/ u64 iclr_b_slot3[4]; /* PCI B Slot 3 Clear Int Reg */ + + u64 __pad9[0x60]; + +/*0x1800*/ u64 iclr_scsi; +/*0x1808*/ u64 iclr_eth; +/*0x1810*/ u64 iclr_bpp; +/*0x1818*/ u64 iclr_au_rec; +/*0x1820*/ u64 iclr_au_play; +/*0x1828*/ u64 iclr_pfail; +/*0x1830*/ u64 iclr_kms; +/*0x1838*/ u64 iclr_flpy; +/*0x1840*/ u64 iclr_shw; +/*0x1848*/ u64 iclr_kbd; +/*0x1850*/ u64 iclr_ms; +/*0x1858*/ u64 iclr_ser; +/*0x1860*/ u64 iclr_tim0; +/*0x1868*/ u64 iclr_tim1; +/*0x1870*/ u64 iclr_ue; +/*0x1878*/ u64 iclr_ce; +/*0x1880*/ u64 iclr_a_err; +/*0x1888*/ u64 iclr_b_err; +/*0x1890*/ u64 iclr_pmgmt; + + u64 __pad10[0x2d]; + + /* Interrupt Retry Timer. */ +/*0x1a00*/ u64 irq_retry; + + u64 __pad11[0x3f]; + + /* Counters/Timers */ +/*0x1c00*/ u64 tim0_cnt; +/*0x1c08*/ u64 tim0_lim; +/*0x1c10*/ u64 tim1_cnt; +/*0x1c18*/ u64 tim1_lim; + + u64 __pad12[0x7c]; + + /* PCI Bus A Registers */ +/*0x2000*/ u64 pci_a_control; /* PCI Bus A Control Register */ +/*0x2008*/ u64 __pad13; +/*0x2010*/ u64 pci_a_afsr; /* PCI Bus A Async Fault Status */ +/*0x2018*/ u64 pci_a_afar; /* PCI Bus A Async Fault Address*/ +/*0x2020*/ u64 pci_a_diag; /* PCI Bus A Diag Register */ + + u64 __pad14[0xfb]; + + /* PCI Bus A/IOMMU Streaming Buffer Registers */ +/*0x2800*/ u64 sbuf_a_control; /* StrBuffer Control */ +/*0x2808*/ u64 sbuf_a_pflush; /* StrBuffer Page Flush */ +/*0x2810*/ u64 sbuf_a_fsync; /* StrBuffer Flush Sync Reg */ + + u64 __pad15[0x2fd]; + + /* PCI Bus B Registers */ +/*0x4000*/ u64 pci_b_control; /* PCI Bus B Control Register */ +/*0x4008*/ u64 __pad16; +/*0x4010*/ u64 pci_b_afsr; /* PCI Bus B Async Fault Status */ +/*0x4018*/ u64 pci_b_afar; /* PCI Bus B Async Fault Address*/ +/*0x4020*/ u64 pci_b_diag; /* PCI Bus B Diag Register */ + + u64 __pad17[0x7b]; + + /* IOMMU diagnostic things */ +/*0x4400*/ u64 iommu_vdiag; /* VADDR Diagnostic Register */ +/*0x4408*/ u64 iommu_tcompare; /* IOMMU TLB Tag Compare */ + + u64 __pad18[0x7e]; + + /* PCI Bus B/IOMMU Streaming Buffer Registers */ +/*0x4800*/ u64 sbuf_b_control; /* StrBuffer Control */ +/*0x4808*/ u64 sbuf_b_pflush; /* StrBuffer Page Flush */ +/*0x4810*/ u64 sbuf_b_fsync; /* StrBuffer Flush Sync Reg */ + + u64 __pad19[0xafd]; + + /* DMA Scoreboard Diagnostic Registers */ +/*0xa000*/ u64 dscore_reg0; /* DMA Scoreboard Diag Reg 0 */ +/*0xa008*/ u64 dscore_reg1; /* DMA Scoreboard Diag Reg 1 */ + + u64 __pad20[0x9e]; + + /* More IOMMU diagnostic things */ +/*0xa500*/ u64 iommu_lru[16]; /* IOMMU LRU Queue Diag */ +/*0xa580*/ u64 iommu_tag[16]; /* IOMMU TLB Tag Diag */ +/*0xa600*/ u64 iommu_data[16]; /* IOMMU TLB Data RAM Diag */ + + u64 __pad21[0x30]; + + /* Interrupt State Diagnostics */ +/*0xa800*/ u64 pci_istate; +/*0xa808*/ u64 obio_istate; + + u64 __pad22[0xfe]; + + /* Streaming Buffer A Diagnostic Area */ +/*0xb000*/ u64 sbuf_a_data[128]; /* StrBuffer Data Ram Diag */ +/*0xb400*/ u64 sbuf_a_errs[128]; /* StrBuffer Error Status Diag*/ +/*0xb800*/ u64 sbuf_a_ptag[16]; /* StrBuffer Page Tag Diag */ +/*0xb880*/ u64 __pad23[16]; +/*0xb900*/ u64 sbuf_a_ltag[16]; /* StrBuffer Line Tag Diag */ + + u64 __pad24[0xd0]; + + /* Streaming Buffer B Diagnostic Area */ +/*0xc000*/ u64 sbuf_b_data[128]; /* StrBuffer Data Ram Diag */ +/*0xc400*/ u64 sbuf_b_errs[128]; /* StrBuffer Error Status Diag*/ +/*0xc800*/ u64 sbuf_b_ptag[16]; /* StrBuffer Page Tag Diag */ +/*0xc880*/ u64 __pad25[16]; +/*0xc900*/ u64 sbuf_b_ltag[16]; /* StrBuffer Line Tag Diag */ +}; + +/* PSYCHO UPA Port ID */ +#define PSYCHO_UPPID_FESC 0xff00000000000000 /* FCode escape, 0xfc */ +#define PSYCHO_UPPID_RESV1 0x00fffff800000000 /* Reserved */ +#define PSYCHO_UPPID_ENV 0x0000000400000000 /* Cannot generate ECC */ +#define PSYCHO_UPPID_ORD 0x0000000200000000 /* One Outstanding Read */ +#define PSYCHO_UPPID_RESV2 0x0000000180000000 /* Reserved */ +#define PSYCHO_UPPID_PDQ 0x000000007e000000 /* Data Queue size */ +#define PSYCHO_UPPID_PRQ 0x0000000001e00000 /* Request Queue size */ +#define PSYCHO_UPPID_UCAP 0x00000000001f0000 /* UPA Capabilities */ +#define PSYCHO_UPPID_JEDEC 0x000000000000ffff /* JEDEC ID for PSYCHO */ + +/* PSYCHO UPA Configuration Register */ +#define PSYCHO_UPCFG_RESV 0xffffffffffffff00 /* Reserved */ +#define PSYCHO_UPCFG_SCIQ1 0x00000000000000f0 /* Unused, always zero */ +#define PSYCHO_UPCFG_SCIQ2 0x000000000000000f /* Requests Queue size 0x2 */ + +/* PSYCHO Control Register */ +#define PSYCHO_CONTROL_IMPL 0xf000000000000000 /* Implementation of this PSYCHO*/ +#define PSYCHO_CONTROL_VER 0x0f00000000000000 /* Version of this PSYCHO */ +#define PSYCHO_CONTROL_MID 0x00f8000000000000 /* UPA Module ID of PSYCHO */ +#define PSYCHO_CONTROL_IGN 0x0007c00000000000 /* Interrupt Group Number */ +#define PSYCHO_CONTROL_RESV 0x00003ffffffffff0 /* Reserved */ +#define PSYCHO_CONTROL_APCKEN 0x0000000000000008 /* Address Parity Check Enable */ +#define PSYCHO_CONTROL_APERR 0x0000000000000004 /* Incoming System Addr Parerr */ +#define PSYCHO_CONTROL_IAP 0x0000000000000002 /* Invert UPA Parity */ +#define PSYCHO_CONTROL_MODE 0x0000000000000001 /* PSYCHO clock mode */ + +/* PSYCHO ECC Control Register */ +#define PSYCHO_ECNTRL_ECCEN 0x8000000000000000 /* Enable ECC Checking */ +#define PSYCHO_ECNTRL_UEEN 0x4000000000000000 /* Enable UE Interrupts */ +#define PSYCHO_ECNTRL_CEEN 0x2000000000000000 /* Enable CE Interrupts */ + +/* Uncorrectable Error AFSR, AFAR holds low 40bits of faulting physical address. */ +#define PSYCHO_UEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */ +#define PSYCHO_UEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */ +#define PSYCHO_UEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */ +#define PSYCHO_UEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */ +#define PSYCHO_UEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */ +#define PSYCHO_UEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ +#define PSYCHO_UEAFSR_RESV1 0x03ff000000000000 /* Reserved */ +#define PSYCHO_UEAFSR_BMSK 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_UEAFSR_DOFF 0x00000000e0000000 /* Doubleword Offset */ +#define PSYCHO_UEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */ +#define PSYCHO_UEAFSR_BLK 0x0000000000800000 /* Trans was block operation */ +#define PSYCHO_UEAFSR_RESV2 0x00000000007fffff /* Reserved */ + +/* Correctable Error AFSR, AFAR holds low 40bits of faulting physical address. */ +#define PSYCHO_CEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */ +#define PSYCHO_CEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */ +#define PSYCHO_CEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */ +#define PSYCHO_CEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */ +#define PSYCHO_CEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */ +#define PSYCHO_CEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ +#define PSYCHO_CEAFSR_RESV1 0x0300000000000000 /* Reserved */ +#define PSYCHO_CEAFSR_ESYND 0x00ff000000000000 /* Syndrome Bits */ +#define PSYCHO_UEAFSR_SIZE 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_CEAFSR_DOFF 0x00000000e0000000 /* Double Offset */ +#define PSYCHO_CEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */ +#define PSYCHO_CEAFSR_BLK 0x0000000000800000 /* Trans was block operation */ +#define PSYCHO_CEAFSR_RESV2 0x00000000007fffff /* Reserved */ + +/* DMA Scoreboard Diagnostic Register(s) */ +#define PSYCHO_DSCORE_VALID 0x8000000000000000 /* Entry is valid */ +#define PSYCHO_DSCORE_C 0x4000000000000000 /* Transaction cacheable */ +#define PSYCHO_DSCORE_READ 0x2000000000000000 /* Transaction was a read */ +#define PSYCHO_DSCORE_TAG 0x1f00000000000000 /* Transaction ID */ +#define PSYCHO_DSCORE_ADDR 0x00fffffffff80000 /* Transaction PADDR */ +#define PSYCHO_DSCORE_BMSK 0x000000000007fff8 /* Bytemask of pending transfer */ +#define PSYCHO_DSCORE_SRC 0x0000000000000007 /* Transaction source */ + +/* PSYCHO PCI Control Register */ +#define PSYCHO_PCICTRL_RESV1 0xfffffff000000000 /* Reserved */ +#define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000 /* Streaming byte hole error */ +#define PSYCHO_PCICTRL_SERR 0x0000000400000000 /* SERR signal asserted */ +#define PSYCHO_PCICTRL_SPEED 0x0000000200000000 /* PCI speed (1 is U2P clock) */ +#define PSYCHO_PCICTRL_RESV2 0x00000001ffc00000 /* Reserved */ +#define PSYCHO_PCICTRL_ARB_PARK 0x0000000000200000 /* PCI arbitration parking */ +#define PSYCHO_PCICTRL_RESV3 0x00000000001ff800 /* Reserved */ +#define PSYCHO_PCICTRL_SBH_INT 0x0000000000000400 /* Streaming byte hole int enab */ +#define PSYCHO_PCICTRL_WEN 0x0000000000000200 /* Power Mgmt Wake Enable */ +#define PSYCHO_PCICTRL_EEN 0x0000000000000100 /* PCI Error Interrupt Enable */ +#define PSYCHO_PCICTRL_RESV4 0x00000000000000c0 /* Reserved */ +#define PSYCHO_PCICTRL_AEN 0x000000000000003f /* PCI DVMA Arbitration Enable */ + +/* PSYCHO PCI AFSR, AFAR holds low 40 bits of physical address causing the fault. */ +#define PSYCHO_PCIAFSR_PMA 0x8000000000000000 /* Primary Master Abort Error */ +#define PSYCHO_PCIAFSR_PTA 0x4000000000000000 /* Primary Target Abort Error */ +#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000 /* Primary Excessive Retries */ +#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000 /* Primary Parity Error */ +#define PSYCHO_PCIAFSR_SMA 0x0800000000000000 /* Secondary Master Abort Error */ +#define PSYCHO_PCIAFSR_STA 0x0400000000000000 /* Secondary Target Abort Error */ +#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000 /* Secondary Excessive Retries */ +#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000 /* Secondary Parity Error */ +#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000 /* Reserved */ +#define PSYCHO_PCIAFSR_SIZE 0x0000ffff00000000 /* Bytemask of failed transfer */ +#define PSYCHO_PCIAFSR_BLK 0x0000000080000000 /* Trans was block operation */ +#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000 /* Reserved */ +#define PSYCHO_PCIAFSR_MID 0x000000003e000000 /* MID causing the error */ +#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffff /* Reserved */ + +/* IOMMU things defined fully in asm-sparc64/iommu.h */ + +/* Streaming Buffer Control Register */ +#define PSYCHO_SBUFCTRL_RESV 0xffffffffffffff80 /* Reserved */ +#define PSYCHO_SBUFCTRL_LRU_LP 0x0000000000000070 /* LRU Lock Pointer */ +#define PSYCHO_SBUFCTRL_LRU_LE 0x0000000000000008 /* LRU Lock Enable */ +#define PSYCHO_SBUFCTRL_RR_DIS 0x0000000000000004 /* Rerun Disable */ +#define PSYCHO_SBUFCTRL_DE 0x0000000000000002 /* Diag Mode Enable */ +#define PSYCHO_SBUFCTRL_SB_EN 0x0000000000000001 /* Streaming Buffer Enable */ + +/* Streaming Buffer Page Invalidate/Flush Register */ +#define PSYCHO_SBUFFLUSH_ADDR 0x00000000ffffe000 /* DVMA Page to be flushed */ +#define PSYCHO_SBUFFLUSH_RESV 0x0000000000001fff /* Ignored bits */ + +/* Streaming Buffer Flush Synchronization Register */ +#define PSYCHO_SBUFSYNC_ADDR 0x000001ffffffffc0 /* Physical address to update */ +#define PSYCHO_SBUFSYNC_RESV 0x000000000000003f /* Ignored bits */ + +/* PSYCHO Interrupt mapping register(s). */ +#define PSYCHO_IMAP_RESV1 0xffffffff00000000 /* Reserved */ +#define PSYCHO_IMAP_VALID 0x0000000080000000 /* This enables delivery. */ +#define PSYCHO_IMAP_TID 0x000000007c000000 /* Target ID (MID to send it to)*/ +#define PSYCHO_IMAP_RESV2 0x0000000003fff800 /* Reserved */ +#define PSYCHO_IMAP_IGN 0x00000000000007c0 /* Interrupt Group Number. */ +#define PSYCHO_IMAP_INO 0x000000000000003f /* Interrupt Number Offset. */ +#define PSYCHO_IMAP_INR 0x00000000000007ff /* Interrupt # (Gfx/UPA_slave) */ + +/* PSYCHO Interrupt clear pseudo register(s). */ +#define PSYCHO_ICLR_RESV1 0xfffffffffffffff0 /* Reserved */ +#define PSYCHO_ICLR_IDLE 0x0000000000000000 /* Transition to idle state. */ +#define PSYCHO_ICLR_TRANSMIT 0x0000000000000001 /* Transition to transmit state */ +#define PSYCHO_ICLR_RESV2 0x0000000000000002 /* Reserved. */ +#define PSYCHO_ICLR_PENDING 0x0000000000000003 /* Transition to pending state. */ + +/* PSYCHO Interrupt Retry Timer register. */ +#define PSYCHO_IRETRY_LIMIT 0x00000000000fffff /* The retry interval. */ + +/* PSYCHO Interrupt State registers. XXX fields to be documented later */ + +/* PSYCHO Counter register. XXX fields to be documented later */ + +/* PSYCHO Limit register. XXX fields to be documented later */ + +/* PSYCHO Performance Monitor Control register. XXX fields to be documented later */ + +/* PSYCHO Performance Monitor Counter register. XXX fields to be documented later */ + +#endif /* !(__SPARC64_PSYCHO_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/sab82532.h linux/include/asm-sparc64/sab82532.h --- v2.1.50/linux/include/asm-sparc64/sab82532.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/sab82532.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,371 @@ +/* $Id: sab82532.h,v 1.2 1997/08/12 04:13:15 ecd Exp $ + * sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#ifndef _SPARC64_SAB82532_H +#define _SPARC64_SAB82532_H + +#include +#include + +struct sab82532_async_rd_regs { + u8 rfifo[0x20]; /* Receive FIFO */ + u8 star; /* Status Register */ + u8 __pad1; + u8 mode; /* Mode Register */ + u8 timr; /* Timer Register */ + u8 xon; /* XON Character */ + u8 xoff; /* XOFF Character */ + u8 tcr; /* Termination Character Register */ + u8 dafo; /* Data Format */ + u8 rfc; /* RFIFO Control Register */ + u8 __pad2; + u8 rbcl; /* Receive Byte Count Low */ + u8 rbch; /* Receive Byte Count High */ + u8 ccr0; /* Channel Configuration Register 0 */ + u8 ccr1; /* Channel Configuration Register 1 */ + u8 ccr2; /* Channel Configuration Register 2 */ + u8 ccr3; /* Channel Configuration Register 3 */ + u8 __pad3[4]; + u8 vstr; /* Version Status Register */ + u8 __pad4[3]; + u8 gis; /* Global Interrupt Status */ + u8 ipc; /* Interrupt Port Configuration */ + u8 isr0; /* Interrupt Status 0 */ + u8 isr1; /* Interrupt Status 1 */ + u8 pvr; /* Port Value Register */ + u8 pis; /* Port Interrupt Status */ + u8 pcr; /* Port Configuration Register */ + u8 ccr4; /* Channel Configuration Register 4 */ +}; + +struct sab82532_async_wr_regs { + u8 xfifo[0x20]; /* Transmit FIFO */ + u8 cmdr; /* Command Register */ + u8 __pad1; + u8 mode; + u8 timr; + u8 xon; + u8 xoff; + u8 tcr; + u8 dafo; + u8 rfc; + u8 __pad2; + u8 xbcl; /* Transmit Byte Count Low */ + u8 xbch; /* Transmit Byte Count High */ + u8 ccr0; + u8 ccr1; + u8 ccr2; + u8 ccr3; + u8 tsax; /* Time-Slot Assignment Reg. Transmit */ + u8 tsar; /* Time-Slot Assignment Reg. Receive */ + u8 xccr; /* Transmit Channel Capacity Register */ + u8 rccr; /* Receive Channel Capacity Register */ + u8 bgr; /* Baud Rate Generator Register */ + u8 tic; /* Transmit Immediate Character */ + u8 mxn; /* Mask XON Character */ + u8 mxf; /* Mask XOFF Character */ + u8 iva; /* Interrupt Vector Address */ + u8 ipc; + u8 imr0; /* Interrupt Mask Register 0 */ + u8 imr1; /* Interrupt Mask Register 1 */ + u8 pvr; + u8 pim; /* Port Interrupt Mask */ + u8 pcr; + u8 ccr4; +}; + +struct sab82532_async_rw_regs { /* Read/Write registers */ + u8 __pad1[0x20]; + u8 __pad2; + u8 __pad3; + u8 mode; + u8 timr; + u8 xon; + u8 xoff; + u8 tcr; + u8 dafo; + u8 rfc; + u8 __pad4; + u8 __pad5; + u8 __pad6; + u8 ccr0; + u8 ccr1; + u8 ccr2; + u8 ccr3; + u8 __pad7; + u8 __pad8; + u8 __pad9; + u8 __pad10; + u8 __pad11; + u8 __pad12; + u8 __pad13; + u8 __pad14; + u8 __pad15; + u8 ipc; + u8 __pad16; + u8 __pad17; + u8 pvr; + u8 __pad18; + u8 pcr; + u8 ccr4; +}; + +union sab82532_async_regs { + __volatile__ struct sab82532_async_rd_regs r; + __volatile__ struct sab82532_async_wr_regs w; + __volatile__ struct sab82532_async_rw_regs rw; +}; + +#define NR_PORTS 2 + +union sab82532_irq_status { + unsigned long stat; + struct { + unsigned char isr0; + unsigned char isr1; + unsigned char ddsr; + } sreg; +}; + +struct sab82532 { + int magic; + int baud_base; + union sab82532_async_regs *regs; + int irq; + int flags; /* defined in tty.h */ + int type; /* SAB82532 version */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int quot; + int x_char; + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + int all_sent; + int is_console; + unsigned char interrupt_mask0; + unsigned char interrupt_mask1; + unsigned char pvr_dtr_bit; + unsigned char pvr_dsr_bit; + unsigned long event; + unsigned long last_active; + int line; + int count; + int blocked_open; + long session; + long pgrp; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct tq_struct tqueue; + struct tq_struct tqueue_hangup; + struct async_icount icount; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + struct wait_queue *delta_msr_wait; + struct sab82532 *next; + struct sab82532 *prev; +}; + + +/* RFIFO Status Byte */ +#define SAB82532_RSTAT_PE 0x80 +#define SAB82532_RSTAT_FE 0x40 +#define SAB82532_RSTAT_PARITY 0x01 + +/* Status Register (STAR) */ +#define SAB82532_STAR_XDOV 0x80 +#define SAB82532_STAR_XFW 0x40 +#define SAB82532_STAR_RFNE 0x20 +#define SAB82532_STAR_FCS 0x10 +#define SAB82532_STAR_TEC 0x08 +#define SAB82532_STAR_CEC 0x04 +#define SAB82532_STAR_CTS 0x02 + +/* Command Register (CMDR) */ +#define SAB82532_CMDR_RMC 0x80 +#define SAB82532_CMDR_RRES 0x40 +#define SAB82532_CMDR_RFRD 0x20 +#define SAB82532_CMDR_STI 0x10 +#define SAB82532_CMDR_XF 0x08 +#define SAB82532_CMDR_XRES 0x01 + +/* Mode Register (MODE) */ +#define SAB82532_MODE_FRTS 0x40 +#define SAB82532_MODE_FCTS 0x20 +#define SAB82532_MODE_FLON 0x10 +#define SAB82532_MODE_RAC 0x08 +#define SAB82532_MODE_RTS 0x04 +#define SAB82532_MODE_TRS 0x02 +#define SAB82532_MODE_TLP 0x01 + +/* Timer Register (TIMR) */ +#define SAB82532_TIMR_CNT_MASK 0xe0 +#define SAB82532_TIMR_VALUE_MASK 0x1f + +/* Data Format (DAFO) */ +#define SAB82532_DAFO_XBRK 0x40 +#define SAB82532_DAFO_STOP 0x20 +#define SAB82532_DAFO_PAR_SPACE 0x00 +#define SAB82532_DAFO_PAR_ODD 0x08 +#define SAB82532_DAFO_PAR_EVEN 0x10 +#define SAB82532_DAFO_PAR_MARK 0x18 +#define SAB82532_DAFO_PARE 0x04 +#define SAB82532_DAFO_CHL8 0x00 +#define SAB82532_DAFO_CHL7 0x01 +#define SAB82532_DAFO_CHL6 0x02 +#define SAB82532_DAFO_CHL5 0x03 + +/* RFIFO Control Register (RFC) */ +#define SAB82532_RFC_DPS 0x40 +#define SAB82532_RFC_DXS 0x20 +#define SAB82532_RFC_RFDF 0x10 +#define SAB82532_RFC_RFTH_1 0x00 +#define SAB82532_RFC_RFTH_4 0x04 +#define SAB82532_RFC_RFTH_16 0x08 +#define SAB82532_RFC_RFTH_32 0x0c +#define SAB82532_RFC_TCDE 0x01 + +/* Received Byte Count High (RBCH) */ +#define SAB82532_RBCH_DMA 0x80 +#define SAB82532_RBCH_CAS 0x20 + +/* Transmit Byte Count High (XBCH) */ +#define SAB82532_XBCH_DMA 0x80 +#define SAB82532_XBCH_CAS 0x20 +#define SAB82532_XBCH_XC 0x10 + +/* Channel Configuration Register 0 (CCR0) */ +#define SAB82532_CCR0_PU 0x80 +#define SAB82532_CCR0_MCE 0x40 +#define SAB82532_CCR0_SC_NRZ 0x00 +#define SAB82532_CCR0_SC_NRZI 0x08 +#define SAB82532_CCR0_SC_FM0 0x10 +#define SAB82532_CCR0_SC_FM1 0x14 +#define SAB82532_CCR0_SC_MANCH 0x18 +#define SAB82532_CCR0_SM_HDLC 0x00 +#define SAB82532_CCR0_SM_SDLC_LOOP 0x01 +#define SAB82532_CCR0_SM_BISYNC 0x02 +#define SAB82532_CCR0_SM_ASYNC 0x03 + +/* Channel Configuration Register 1 (CCR1) */ +#define SAB82532_CCR1_ODS 0x10 +#define SAB82532_CCR1_BCR 0x08 +#define SAB82532_CCR1_CM_MASK 0x07 + +/* Channel Configuration Register 2 (CCR2) */ +#define SAB82532_CCR2_SOC1 0x80 +#define SAB82532_CCR2_SOC0 0x40 +#define SAB82532_CCR2_BR9 0x80 +#define SAB82532_CCR2_BR8 0x40 +#define SAB82532_CCR2_BDF 0x20 +#define SAB82532_CCR2_SSEL 0x10 +#define SAB82532_CCR2_XCS0 0x20 +#define SAB82532_CCR2_RCS0 0x10 +#define SAB82532_CCR2_TOE 0x08 +#define SAB82532_CCR2_RWX 0x04 +#define SAB82532_CCR2_DIV 0x01 + +/* Channel Configuration Register 3 (CCR3) */ +#define SAB82532_CCR3_PSD 0x01 + +/* Time Slot Assignment Register Transmit (TSAX) */ +#define SAB82532_TSAX_TSNX_MASK 0xfc +#define SAB82532_TSAX_XCS2 0x02 /* see also CCR2 */ +#define SAB82532_TSAX_XCS1 0x01 + +/* Time Slot Assignment Register Receive (TSAR) */ +#define SAB82532_TSAR_TSNR_MASK 0xfc +#define SAB82532_TSAR_RCS2 0x02 /* see also CCR2 */ +#define SAB82532_TSAR_RCS1 0x01 + +/* Version Status Register (VSTR) */ +#define SAB82532_VSTR_CD 0x80 +#define SAB82532_VSTR_DPLA 0x40 +#define SAB82532_VSTR_VN_MASK 0x0f +#define SAB82532_VSTR_VN_1 0x00 +#define SAB82532_VSTR_VN_2 0x01 +#define SAB82532_VSTR_VN_3_2 0x02 + +/* Global Interrupt Status Register (GIS) */ +#define SAB82532_GIS_PI 0x80 +#define SAB82532_GIS_ISA1 0x08 +#define SAB82532_GIS_ISA0 0x04 +#define SAB82532_GIS_ISB1 0x02 +#define SAB82532_GIS_ISB0 0x01 + +/* Interrupt Vector Address (IVA) */ +#define SAB82532_IVA_MASK 0xf1 + +/* Interrupt Port Configuration (IPC) */ +#define SAB82532_IPC_VIS 0x80 +#define SAB82532_IPC_SLA1 0x10 +#define SAB82532_IPC_SLA0 0x08 +#define SAB82532_IPC_CASM 0x04 +#define SAB82532_IPC_IC_OPEN_DRAIN 0x00 +#define SAB82532_IPC_IC_ACT_LOW 0x01 +#define SAB82532_IPC_IC_ACT_HIGH 0x03 + +/* Interrupt Status Register 0 (ISR0) */ +#define SAB82532_ISR0_TCD 0x80 +#define SAB82532_ISR0_TIME 0x40 +#define SAB82532_ISR0_PERR 0x20 +#define SAB82532_ISR0_FERR 0x10 +#define SAB82532_ISR0_PLLA 0x08 +#define SAB82532_ISR0_CDSC 0x04 +#define SAB82532_ISR0_RFO 0x02 +#define SAB82532_ISR0_RPF 0x01 + +/* Interrupt Status Register 1 (ISR1) */ +#define SAB82532_ISR1_BRK 0x80 +#define SAB82532_ISR1_BRKT 0x40 +#define SAB82532_ISR1_ALLS 0x20 +#define SAB82532_ISR1_XOFF 0x10 +#define SAB82532_ISR1_TIN 0x08 +#define SAB82532_ISR1_CSC 0x04 +#define SAB82532_ISR1_XON 0x02 +#define SAB82532_ISR1_XPR 0x01 + +/* Interrupt Mask Register 0 (IMR0) */ +#define SAB82532_IMR0_TCD 0x80 +#define SAB82532_IMR0_PERR 0x20 +#define SAB82532_IMR0_SCD 0x10 +#define SAB82532_IMR0_PLLA 0x08 +#define SAB82532_IMR0_CDSC 0x04 +#define SAB82532_IMR0_RFO 0x02 +#define SAB82532_IMR0_RPF 0x01 +#define SAB82532_IMR0_OR_ME_IN 0x40 + +/* Interrupt Mask Register 1 (IMR1) */ +#define SAB82532_IMR1_ALLS 0x20 +#define SAB82532_IMR1_XDU 0x10 +#define SAB82532_IMR1_TIN 0x08 +#define SAB82532_IMR1_CSC 0x04 +#define SAB82532_IMR1_XMR 0x02 +#define SAB82532_IMR1_XPR 0x01 +#define SAB82532_IMR1_OR_ME_IN 0xc0 + +/* Port Interrupt Status Register (PIS) */ +#define SAB82532_PIS_SYNC_B 0x08 +#define SAB82532_PIS_DTR_B 0x04 +#define SAB82532_PIS_DTR_A 0x02 +#define SAB82532_PIS_SYNC_A 0x01 + +/* Channel Configuration Register 4 (CCR4) */ +#define SAB82532_CCR4_MCK4 0x80 +#define SAB82532_CCR4_EBRG 0x40 +#define SAB82532_CCR4_TST1 0x20 +#define SAB82532_CCR4_ICD 0x10 + + +#endif /* !(_SPARC64_SAB82532_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/sbus.h linux/include/asm-sparc64/sbus.h --- v2.1.50/linux/include/asm-sparc64/sbus.h Mon Apr 14 16:28:23 1997 +++ linux/include/asm-sparc64/sbus.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: sbus.h,v 1.3 1997/03/21 17:57:24 jj Exp $ +/* $Id: sbus.h,v 1.5 1997/08/12 04:13:16 ecd Exp $ * sbus.h: Defines for the Sun SBus. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -87,9 +87,7 @@ for((device) = (bus)->devices; (device); (device)=(device)->next) #define for_all_sbusdev(device, bus) \ - for((bus) = SBus_chain, (device) = (bus)->devices; (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) - -/* XXX This is promlib stuff, what is it doing here? XXX */ + for((bus) = SBus_chain, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0))) /* Apply promlib probed SBUS ranges to registers. */ extern void prom_apply_sbus_ranges(struct linux_sbus *sbus, diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h --- v2.1.50/linux/include/asm-sparc64/semaphore.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/semaphore.h Sat Aug 16 09:51:10 1997 @@ -38,20 +38,28 @@ extern __inline__ void down(struct semaphore * sem) { - if (atomic_dec_return(&sem->count) < 0) + int result; + + result = atomic_dec_return(&sem->count); + membar("#StoreLoad | #StoreStore"); + if (result < 0) __down(sem); } extern __inline__ int down_interruptible(struct semaphore *sem) { - int ret = 0; - if (atomic_dec_return(&sem->count) < 0) + int result, ret = 0; + + result = atomic_dec_return(&sem->count); + membar("#StoreLoad | #StoreStore"); + if (result < 0) ret = __down_interruptible(sem); return ret; } extern __inline__ void up(struct semaphore * sem) { + membar("#StoreStore | #LoadStore"); if (atomic_inc_return(&sem->count) <= 0) __up(sem); } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/shmparam.h linux/include/asm-sparc64/shmparam.h --- v2.1.50/linux/include/asm-sparc64/shmparam.h Mon Dec 30 02:00:03 1996 +++ linux/include/asm-sparc64/shmparam.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: shmparam.h,v 1.1 1996/12/26 14:22:36 davem Exp $ */ +/* $Id: shmparam.h,v 1.2 1997/08/04 16:16:55 davem Exp $ */ #ifndef _ASMSPARC64_SHMPARAM_H #define _ASMSPARC64_SHMPARAM_H @@ -41,7 +41,7 @@ #define SHMMNI (1<<_SHM_ID_BITS) /* max num of segs system wide */ #define SHMALL /* max shm system wide (pages) */ \ (1<<(_SHM_IDX_BITS+_SHM_ID_BITS)) -#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ +#define SHMLBA (PAGE_SIZE<<1) /* attach addr a multiple of this */ #define SHMSEG SHMMNI /* max shared segs per process */ #endif /* _ASMSPARC64_SHMPARAM_H */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h --- v2.1.50/linux/include/asm-sparc64/smp.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/smp.h Sat Aug 16 09:51:10 1997 @@ -6,6 +6,7 @@ #ifndef _SPARC64_SMP_H #define _SPARC64_SMP_H +#include #include #ifndef __ASSEMBLY__ @@ -29,8 +30,20 @@ /* Per processor Sparc parameters we need. */ +/* Keep this a multiple of 64-bytes for cache reasons. */ struct cpuinfo_sparc { - unsigned long udelay_val; /* that's it */ + /* Dcache line 1 */ + unsigned long irq_count; + unsigned int multiplier; + unsigned int counter; + unsigned long last_tlbversion_seen; + unsigned long pgcache_size; + + /* Dcache line 2 */ + unsigned long *pgd_cache; + unsigned long *pmd_cache; + unsigned long *pte_cache; + unsigned long udelay_val; }; extern struct cpuinfo_sparc cpu_data[NR_CPUS]; @@ -49,21 +62,8 @@ * Private routines/data */ -extern int smp_found_cpus; extern unsigned char boot_cpu_id; extern unsigned long cpu_present_map; -extern __volatile__ unsigned long smp_invalidate_needed[NR_CPUS]; -extern __volatile__ unsigned long kernel_counter; -extern __volatile__ unsigned char active_kernel_processor; -extern void smp_message_irq(void); -extern unsigned long ipi_count; -extern __volatile__ unsigned long kernel_counter; -extern __volatile__ unsigned long syscall_count; - -extern void print_lock_state(void); - -typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long); /* * General functions that each host system must provide. @@ -88,30 +88,12 @@ #define smp_processor_id() (current->processor) -extern __volatile__ unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */ #endif /* !(__ASSEMBLY__) */ -/* Sparc specific messages. */ -#define MSG_CROSS_CALL 0x0005 /* run func on cpus */ - -/* Empirical PROM processor mailbox constants. If the per-cpu mailbox - * contains something other than one of these then the ipi is from - * Linux's active_kernel_processor. This facility exists so that - * the boot monitor can capture all the other cpus when one catches - * a watchdog reset or the user enters the monitor using L1-A keys. - */ -#define MBOX_STOPCPU 0xFB -#define MBOX_IDLECPU 0xFC -#define MBOX_IDLECPU2 0xFD -#define MBOX_STOPCPU2 0xFE - -#define PROC_CHANGE_PENALTY 20 - -#define SMP_FROM_INT 1 -#define SMP_FROM_SYSCALL 2 +#define PROC_CHANGE_PENALTY 20 #endif /* !(__SMP__) */ -#define NO_PROC_ID 0xFF +#define NO_PROC_ID 0xFF #endif /* !(_SPARC64_SMP_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/smp_lock.h linux/include/asm-sparc64/smp_lock.h --- v2.1.50/linux/include/asm-sparc64/smp_lock.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/smp_lock.h Sat Aug 16 09:51:10 1997 @@ -28,6 +28,7 @@ __cli(); \ (task)->lock_depth = 0; \ klock_info.akp = NO_PROC_ID; \ + membar("#LoadStore | #StoreStore"); \ klock_info.kernel_flag = 0; \ } \ release_irqlock(cpu); \ @@ -45,7 +46,7 @@ " mov %1, %%g2" \ : /* No outputs. */ \ : "r" (klip), "r" (depth) \ - : "g2", "g3", "g5", "g7", "memory", "cc"); \ + : "g2", "g3", "g5", "memory", "cc"); \ } \ } while(0) @@ -63,9 +64,9 @@ __asm__ __volatile__(" mov %%o7, %%g5 call ___lock_kernel - ld [%%g6 + %0], %%g2 + lduw [%%g6 + %0], %%g2 " : : "i" (AOFF_task_lock_depth), "r" (klip) - : "g2", "g3", "g5", "g7", "memory", "cc"); + : "g2", "g3", "g5", "memory", "cc"); } /* Release kernel global lock. */ @@ -76,7 +77,7 @@ __asm__ __volatile__(" mov %%o7, %%g5 call ___unlock_kernel - ld [%%g6 + %0], %%g2 + lduw [%%g6 + %0], %%g2 " : : "i" (AOFF_task_lock_depth), "r" (klip) : "g2", "g3", "g5", "memory", "cc"); } diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h --- v2.1.50/linux/include/asm-sparc64/spinlock.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/spinlock.h Sat Aug 16 09:51:10 1997 @@ -68,33 +68,35 @@ typedef unsigned char spinlock_t; #define SPIN_LOCK_UNLOCKED 0 -#define spin_lock_init(lock) (*(lock) = 0) -#define spin_unlock_wait(lock) do { barrier(); } while(*(volatile spinlock_t *)lock) + +#define spin_lock_init(lock) (*((unsigned char *)(lock)) = 0) + +#define spin_unlock_wait(lock) \ +do { membar("#LoadLoad"); \ +} while(*((volatile unsigned char *)lock)) extern __inline__ void spin_lock(spinlock_t *lock) { __asm__ __volatile__(" -1: ldstub [%0], %%g2 - brz,pt %%g2, 2f - membar #LoadLoad | #LoadStore - b,a %%xcc, 3f -2: - .text 2 -3: ldub [%0], %%g2 -4: brnz,a,pt %%g2, 4b - ldub [%0], %%g2 - b,a 1b +1: ldstub [%0], %%g7 + brnz,pn %%g7, 2f + membar #StoreLoad | #StoreStore + .subsection 2 +2: ldub [%0], %%g7 + brnz,pt %%g7, 2b + membar #LoadLoad + b,a,pt %%xcc, 1b .previous " : /* no outputs */ : "r" (lock) - : "g2", "memory"); + : "g7", "memory"); } extern __inline__ int spin_trylock(spinlock_t *lock) { unsigned int result; __asm__ __volatile__("ldstub [%1], %0\n\t" - "membar #LoadLoad | #LoadStore" + "membar #StoreLoad | #StoreStore" : "=r" (result) : "r" (lock) : "memory"); @@ -104,7 +106,7 @@ extern __inline__ void spin_unlock(spinlock_t *lock) { __asm__ __volatile__("membar #StoreStore | #LoadStore\n\t" - "stb %%g0, [%0]" + "stb %%g0, [%0]\n\t" : /* No outputs */ : "r" (lock) : "memory"); @@ -114,20 +116,18 @@ { __asm__ __volatile__(" wrpr %%g0, 15, %%pil -1: ldstub [%0], %%g2 - brz,pt %%g2, 2f - membar #LoadLoad | #LoadStore - b,a 3f -2: - .text 2 -3: ldub [%0], %%g2 -4: brnz,a,pt %%g2, 4b - ldub [%0], %%g2 - b,a 1b +1: ldstub [%0], %%g7 + brnz,pn %%g7, 2f + membar #StoreLoad | #StoreStore + .subsection 2 +2: ldub [%0], %%g7 + brnz,pt %%g7, 2b + membar #LoadLoad + b,a,pt %%xcc, 1b .previous " : /* no outputs */ : "r" (lock) - : "g2", "memory"); + : "g7", "memory"); } extern __inline__ void spin_unlock_irq(spinlock_t *lock) @@ -147,20 +147,18 @@ __asm__ __volatile__( \ "\n rdpr %%pil, %0\n" \ " wrpr %%g0, 15, %%pil\n" \ - "1: ldstub [%1], %%g2\n" \ - " brz,pt %%g2, 2f\n" \ - " membar #LoadLoad | #LoadStore\n" \ - " b,a 3f\n" \ - "2:\n" \ - " .text 2\n" \ - "3: ldub [%1], %%g2\n" \ - "4: brnz,a,pt %%g2, 4b\n" \ - " ldub [%1], %%g2\n" \ - " b,a 1b\n" \ + "1: ldstub [%1], %%g7\n" \ + " brnz,pn %%g7, 2f\n" \ + " membar #StoreLoad | #StoreStore\n" \ + " .subsection 2\n" \ + "2: ldub [%1], %%g7\n" \ + " brnz,pt %%g7, 2b\n" \ + " membar #LoadLoad\n" \ + " b,a,pt %%xcc, 1b\n" \ " .previous\n" \ : "=&r" (flags) \ : "r" (lp) \ - : "g2", "memory"); \ + : "g7", "memory"); \ } while(0) extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) @@ -182,94 +180,83 @@ extern __inline__ void read_lock(rwlock_t *rw) { __asm__ __volatile__(" - ldx [%0], %%g2 -1: brgez,pt %%g2, 4f - add %%g2, 1, %%g3 - b,a 2f -4: casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 - membar #LoadLoad | #LoadStore - .text 2 -2: ldx [%0], %%g2 -3: brlz,a,pt %%g2, 3b - ldx [%0], %%g2 - b 4b - add %%g2, 1, %%g3 +1: ldx [%0], %%g5 + brlz,pn %%g5, 2f +4: add %%g5, 1, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + membar #StoreLoad | #StoreStore + .subsection 2 +2: ldx [%0], %%g5 + brlz,pt %%g5, 2b + membar #LoadLoad + b,a,pt %%xcc, 4b .previous " : /* no outputs */ : "r" (rw) - : "g2", "g3", "cc", "memory"); + : "g5", "g7", "cc", "memory"); } extern __inline__ void read_unlock(rwlock_t *rw) { __asm__ __volatile__(" - membar #StoreStore | #LoadStore - ldx [%0], %%g2 -1: sub %%g2, 1, %%g3 - casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 +1: ldx [%0], %%g5 + sub %%g5, 1, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + membar #StoreLoad | #StoreStore " : /* no outputs */ : "r" (rw) - : "g2", "g3", "cc", "memory"); + : "g5", "g7", "cc", "memory"); } extern __inline__ void write_lock(rwlock_t *rw) { __asm__ __volatile__(" - sethi %%uhi(0x8000000000000000), %%g5 - ldx [%0], %%g2 - sllx %%g5, 32, %%g5 -1: brgez,pt %%g2, 4f - or %%g2, %%g5, %%g3 - b,a 5f -4: casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 - andncc %%g3, %%g5, %%g0 - be,pt %%xcc, 2f - membar #LoadLoad | #LoadStore - b,a 7f -2: - .text 2 -7: ldx [%0], %%g2 -3: andn %%g2, %%g5, %%g3 - casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 3b - ldx [%0], %%g2 - membar #LoadLoad | #LoadStore -5: ldx [%0], %%g2 -6: brlz,a,pt %%g2, 6b - ldx [%0], %%g2 - b 4b - or %%g2, %%g5, %%g3 + sethi %%uhi(0x8000000000000000), %%g3 + sllx %%g3, 32, %%g3 +1: ldx [%0], %%g5 + brlz,pn %%g5, 5f +4: or %%g5, %%g3, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + andncc %%g7, %%g3, %%g0 + bne,pn %%xcc, 7f + membar #StoreLoad | #StoreStore + .subsection 2 +7: ldx [%0], %%g5 + andn %%g5, %%g3, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 7b + membar #StoreLoad | #StoreStore +5: ldx [%0], %%g5 + brnz,pt %%g5, 5b + membar #LoadLoad + b,a,pt %%xcc, 4b .previous " : /* no outputs */ : "r" (rw) - : "g2", "g3", "g5", "memory", "cc"); + : "g3", "g5", "g7", "memory", "cc"); } extern __inline__ void write_unlock(rwlock_t *rw) { __asm__ __volatile__(" - membar #StoreStore | #LoadStore - sethi %%uhi(0x8000000000000000), %%g5 - ldx [%0], %%g2 - sllx %%g5, 32, %%g5 -1: andn %%g2, %%g5, %%g3 - casx [%0], %%g2, %%g3 - cmp %%g2, %%g3 - bne,a,pn %%xcc, 1b - ldx [%0], %%g2 + sethi %%uhi(0x8000000000000000), %%g3 + sllx %%g3, 32, %%g3 +1: ldx [%0], %%g5 + andn %%g5, %%g3, %%g7 + casx [%0], %%g5, %%g7 + cmp %%g5, %%g7 + bne,pn %%xcc, 1b + membar #StoreLoad | #StoreStore " : /* no outputs */ : "r" (rw) - : "g2", "g3", "g5", "memory", "cc"); + : "g3", "g5", "g7", "memory", "cc"); } #define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0) diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/sysio.h linux/include/asm-sparc64/sysio.h --- v2.1.50/linux/include/asm-sparc64/sysio.h Mon Apr 14 16:28:24 1997 +++ linux/include/asm-sparc64/sysio.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: sysio.h,v 1.2 1997/04/03 12:26:45 davem Exp $ +/* $Id: sysio.h,v 1.6 1997/08/15 06:44:53 davem Exp $ * sysio.h: UltraSparc sun5 specific SBUS definitions. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -49,7 +49,7 @@ * slot 5) MACIO * slot 6) SLAVIO * - * On Sunfire/Wildfire enterprise boxen these upper slots + * On Sunfire/Starfire/Wildfire enterprise boxen these upper slots * are unused. */ /*0x2020*/ u64 sbus_s0cfg; /* SBUS Slot 0 Config */ @@ -72,83 +72,83 @@ /* SBUS/IOMMU Streaming Buffer Registers */ /*0x2800*/ u64 sbuf_control; /* StrBuffer Control */ /*0x2808*/ u64 sbuf_pflush; /* StrBuffer Page Flush */ -/*0x2810*/ u64 sbus_fsync; /* StrBuffer Flush Synchronization Reg */ +/*0x2810*/ u64 sbuf_fsync; /* StrBuffer Flush Synchronization Reg */ u64 __pad4[0x7d]; /* Interrupt mapping/control registers */ -/*0x2c00*/ u32 imap_slot0, _uim0; /* SBUS Slot 0 Int Mapping */ -/*0x2c08*/ u32 imap_slot1, _uim1; /* SBUS Slot 1 Int Mapping */ -/*0x2c10*/ u32 imap_slot2, _uim2; /* SBUS Slot 2 Int Mapping */ -/*0x2c18*/ u32 imap_slot3, _uim3; /* SBUS Slot 3 Int Mapping */ +/*0x2c00*/ u32 _uim0, imap_slot0; /* SBUS Slot 0 Int Mapping */ +/*0x2c08*/ u32 _uim1, imap_slot1; /* SBUS Slot 1 Int Mapping */ +/*0x2c10*/ u32 _uim2, imap_slot2; /* SBUS Slot 2 Int Mapping */ +/*0x2c18*/ u32 _uim3, imap_slot3; /* SBUS Slot 3 Int Mapping */ /* Interrupt Retry Timer. */ -/*0x2c20*/ u32 irq_retry, _irpad; +/*0x2c20*/ u32 _irpad, irq_retry; u64 __pad5[0x7b]; /* The following are only used on Fusion/Electron/Pulsar - * desktop systems, they mean nothing on Sunfire/Wildfire + * desktop systems, they mean nothing on Sunfire/Starfire/Wildfire */ -/*0x3000*/ u32 imap_scsi, _uis; /* SCSI Int Mapping */ -/*0x3008*/ u32 imap_eth, _uie; /* Ethernet Int Mapping */ -/*0x3010*/ u32 imap_bpp, _uip; /* Parallel Port Int Mapping */ -/*0x3018*/ u32 imap_audio, _uia; /* Audio Int Mapping */ -/*0x3020*/ u32 imap_pfail, _uipf; /* Power Fail Int Mapping */ -/*0x3028*/ u32 imap_kms, _uik; /* Kbd/Mouse/Serial Int Mapping */ -/*0x3030*/ u32 imap_flpy, _uif; /* Floppy Int Mapping */ -/*0x3038*/ u32 imap_shw, _uishw; /* Spare HW Int Mapping */ -/*0x3040*/ u32 imap_kbd, _uikbd; /* Kbd Only Int Mapping */ -/*0x3048*/ u32 imap_ms, _uims; /* Mouse Only Int Mapping */ -/*0x3050*/ u32 imap_ser, _uiser; /* Serial Only Int Mapping */ +/*0x3000*/ u32 _uis, imap_scsi; /* SCSI Int Mapping */ +/*0x3008*/ u32 _uie, imap_eth; /* Ethernet Int Mapping */ +/*0x3010*/ u32 _uip, imap_bpp; /* Parallel Port Int Mapping */ +/*0x3018*/ u32 _uia, imap_audio; /* Audio Int Mapping */ +/*0x3020*/ u32 _uipf, imap_pfail; /* Power Fail Int Mapping */ +/*0x3028*/ u32 _uik, imap_kms; /* Kbd/Mouse/Serial Int Mapping */ +/*0x3030*/ u32 _uif, imap_flpy; /* Floppy Int Mapping */ +/*0x3038*/ u32 _uishw, imap_shw; /* Spare HW Int Mapping */ +/*0x3040*/ u32 _uikbd, imap_kbd; /* Kbd Only Int Mapping */ +/*0x3048*/ u32 _uims, imap_ms; /* Mouse Only Int Mapping */ +/*0x3050*/ u32 _uiser, imap_ser; /* Serial Only Int Mapping */ /*0x3058*/ u64 _imap_unused; -/*0x3060*/ u32 imap_tim0, _uit0; /* Timer 0 Int Mapping */ -/*0x3068*/ u32 imap_tim1, _uit1; /* Timer 1 Int Mapping */ -/*0x3070*/ u32 imap_ue, _uiue; /* UE Int Mapping */ -/*0x3078*/ u32 imap_ce, _uice; /* CE Int Mapping */ -/*0x3080*/ u32 imap_sberr, _uisbe; /* SBUS Err Int Mapping */ -/*0x3088*/ u32 imap_pmgmt, _uipm; /* Power Mgmt Int Mapping */ -/*0x3090*/ u32 imap_gfx, _uigfx; /* OB Graphics Int Mapping */ -/*0x3098*/ u32 imap_eupa, _uieupa; /* UPA Expansion Int Mapping */ +/*0x3060*/ u32 _uit0, imap_tim0; /* Timer 0 Int Mapping */ +/*0x3068*/ u32 _uit1, imap_tim1; /* Timer 1 Int Mapping */ +/*0x3070*/ u32 _uiue, imap_ue; /* UE Int Mapping */ +/*0x3078*/ u32 _uice, imap_ce; /* CE Int Mapping */ +/*0x3080*/ u32 _uisbe, imap_sberr; /* SBUS Err Int Mapping */ +/*0x3088*/ u32 _uipm, imap_pmgmt; /* Power Mgmt Int Mapping */ +/*0x3090*/ u32 _uigfx, imap_gfx; /* OB Graphics Int Mapping */ +/*0x3098*/ u32 _uieupa, imap_eupa; /* UPA Expansion Int Mapping */ u64 __pad6[0x6c]; /* Interrupt Clear Registers */ -/*0x3400*/ u64 iclr_unused0; -/*0x3408*/ u32 iclr_slot0, _ucs0; +/*0x3400*/ u32 __ucu0, iclr_unused0; +/*0x3408*/ u32 _ucs0, iclr_slot0; u64 __pad7[0x7]; -/*0x3448*/ u32 iclr_slot1, _ucs1; +/*0x3448*/ u32 _ucs1, iclr_slot1; u64 __pad8[0x7]; -/*0x3488*/ u32 iclr_slot2, _ucs2; +/*0x3488*/ u32 _ucs2, iclr_slot2; u64 __pad9[0x7]; -/*0x34c8*/ u32 iclr_slot3, _ucs3; +/*0x34c8*/ u32 _ucs3, iclr_slot3; u64 __pad10[0x66]; -/*0x3800*/ u32 iclr_scsi, _ucscsi; -/*0x3808*/ u32 iclr_eth, _uceth; -/*0x3810*/ u32 iclr_bpp, _ucbpp; -/*0x3818*/ u32 iclr_audio, _ucaudio; -/*0x3820*/ u32 iclr_pfail, _ucpfail; -/*0x3828*/ u32 iclr_kms, _uckms; -/*0x3830*/ u32 iclr_flpt, _ucflpy; -/*0x3838*/ u32 iclr_shw, _ucshw; -/*0x3840*/ u32 iclr_kbd, _uckbd; -/*0x3848*/ u32 iclr_ms, _ucms; -/*0x3850*/ u32 iclr_ser, _ucser; +/*0x3800*/ u32 _ucscsi, iclr_scsi; +/*0x3808*/ u32 _uceth, iclr_eth; +/*0x3810*/ u32 _ucbpp, iclr_bpp; +/*0x3818*/ u32 _ucaudio, iclr_audio; +/*0x3820*/ u32 _ucpfail, iclr_pfail; +/*0x3828*/ u32 _uckms, iclr_kms; +/*0x3830*/ u32 _ucflpy, iclr_flpt; +/*0x3838*/ u32 _ucshw, iclr_shw; +/*0x3840*/ u32 _uckbd, iclr_kbd; +/*0x3848*/ u32 _ucms, iclr_ms; +/*0x3850*/ u32 _ucser, iclr_ser; /*0x3858*/ u64 iclr_unused1; -/*0x3860*/ u32 iclr_tim0, _uctim0; -/*0x3868*/ u32 iclr_tim1, _uctim1; -/*0x3870*/ u32 iclr_ue, _ucue; -/*0x3878*/ u32 iclr_ce, _ucce; -/*0x3880*/ u32 iclr_serr, _ucserr; -/*0x3888*/ u32 iclr_pmgmt, _ucpmgmt; +/*0x3860*/ u32 _uctim0, iclr_tim0; +/*0x3868*/ u32 _uctim1, iclr_tim1; +/*0x3870*/ u32 _ucue, iclr_ue; +/*0x3878*/ u32 _ucce, iclr_ce; +/*0x3880*/ u32 _ucserr, iclr_serr; +/*0x3888*/ u32 _ucpmgmt, iclr_pmgmt; u64 __pad11[0x6e]; /* Counters/Timers */ -/*0x3c00*/ u32 tim0_cnt, _tim0_u0; -/*0x3c08*/ u32 tim0_lim, _tim0_u1; -/*0x3c10*/ u32 tim1_cnt, _tim1_u0; -/*0x3c18*/ u32 tim1_lim, _tim1_u1; +/*0x3c00*/ u64 tim0_cnt; +/*0x3c08*/ u64 tim0_lim; +/*0x3c10*/ u64 tim1_cnt; +/*0x3c18*/ u64 tim1_lim; u64 __pad12[0x7c]; @@ -169,11 +169,13 @@ /*0x4580*/ u64 iommu_tag[16]; /* IOMMU TLB Tag Diagnostic Access */ /*0x4600*/ u64 iommu_data[32]; /* IOMMU TLB Data RAM Diagnostic Access */ + u64 __pad15[0x20]; + /* Interrupt State Diagnostics */ /*0x4800*/ u64 sbus_istate; /*0x4808*/ u64 obio_istate; - u64 __pad15[0xfe]; + u64 __pad16[0xfe]; /* Streaming Buffer Diagnostic Area */ /*0x5000*/ u64 sbuf_data[128]; /* StrBuffer Data Ram Diagnostic */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h --- v2.1.50/linux/include/asm-sparc64/system.h Mon Aug 4 16:25:40 1997 +++ linux/include/asm-sparc64/system.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.29 1997/07/24 16:48:32 davem Exp $ */ +/* $Id: system.h,v 1.35 1997/08/07 03:53:00 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -6,8 +6,6 @@ #include #include -#define NCPUS 4 /* No SMP yet */ - #ifndef __ASSEMBLY__ /* * Sparc (general) CPU types @@ -103,7 +101,7 @@ #define membar(type) __asm__ __volatile__ ("membar " type : : : "memory"); -#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr)) +#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") #define flushw_all() __asm__ __volatile__("flushw") @@ -131,6 +129,16 @@ * I do not clobber it, when in fact I do. Please, * when modifying this code inspect output of sched.s very * carefully to make sure things still work. -DaveM + * + * SMP NOTE: At first glance it looks like there is a tiny + * race window here at the end. The possible problem + * would be if a tlbcachesync MONDO vector got delivered + * to us right before we set the final %g6 thread reg + * value. But that is impossible since only the holder + * of scheduler_lock can send a tlbcachesync MONDO and + * by definition we hold it right now. Normal tlb + * flush xcalls can come in, but those are safe and do + * not reference %g6. */ #define switch_to(prev, next) \ do { __label__ switch_continue; \ @@ -142,7 +150,6 @@ "rdpr %%pstate, %%g2\n\t" \ "wrpr %%g2, 0x3, %%pstate\n\t" \ "flushw\n\t" \ -/*XXX*/ "wr %%g0, 0, %%fprs\n\t" \ "stx %%i6, [%%sp + 2047 + 0x70]\n\t" \ "stx %%i7, [%%sp + 2047 + 0x78]\n\t" \ "rdpr %%wstate, %%o5\n\t" \ @@ -151,6 +158,7 @@ "rdpr %%cwp, %%o5\n\t" \ "stx %%o7, [%%g6 + %4]\n\t" \ "st %%o5, [%%g6 + %5]\n\t" \ + "membar #Sync\n\t" \ "mov %0, %%g6\n\t" \ "ld [%0 + %5], %%g1\n\t" \ "wrpr %%g1, %%cwp\n\t" \ @@ -176,30 +184,35 @@ "o0", "o1", "o2", "o3", "o4", "o5"); \ switch_continue: } while(0) -/* Unlike the hybrid v7/v8 kernel, we can assume swap exists under V9. */ -extern __inline__ unsigned long xchg_u32(__volatile__ unsigned int *m, unsigned int val) +extern __inline__ unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val) { - __asm__ __volatile__("swap [%2], %0" - : "=&r" (val) - : "0" (val), "r" (m)); + __asm__ __volatile__(" + mov %0, %%g5 +1: lduw [%2], %%g7 + cas [%2], %%g7, %0 + cmp %%g7, %0 + bne,a,pn %%icc, 1b + mov %%g5, %0 + membar #StoreLoad | #StoreStore +" : "=&r" (val) + : "0" (val), "r" (m) + : "g5", "g7", "cc", "memory"); return val; } -/* Bolix, must use casx for 64-bit values. */ -extern __inline__ unsigned long xchg_u64(__volatile__ unsigned long *m, - unsigned long val) +extern __inline__ unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val) { - unsigned long temp; __asm__ __volatile__(" - mov %0, %%g1 -1: ldx [%3], %1 - casx [%3], %1, %0 - cmp %1, %0 + mov %0, %%g5 +1: ldx [%2], %%g7 + casx [%2], %%g7, %0 + cmp %%g7, %0 bne,a,pn %%xcc, 1b - mov %%g1, %0 -" : "=&r" (val), "=&r" (temp) + mov %%g5, %0 + membar #StoreLoad | #StoreStore +" : "=&r" (val) : "0" (val), "r" (m) - : "g1", "cc"); + : "g5", "g7", "cc", "memory"); return val; } @@ -213,9 +226,9 @@ { switch (size) { case 4: - return xchg_u32(ptr, x); + return xchg32(ptr, x); case 8: - return xchg_u64(ptr, x); + return xchg64(ptr, x); }; __xchg_called_with_bad_pointer(); return x; diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/termbits.h linux/include/asm-sparc64/termbits.h --- v2.1.50/linux/include/asm-sparc64/termbits.h Tue May 13 22:41:18 1997 +++ linux/include/asm-sparc64/termbits.h Sat Aug 16 09:51:10 1997 @@ -148,13 +148,18 @@ #define HUPCL 0x00000400 #define CLOCAL 0x00000800 #define CBAUDEX 0x00001000 -/* We'll never see these speeds with the Zilogs, but for completeness... */ #define B57600 0x00001001 #define B115200 0x00001002 #define B230400 0x00001003 #define B460800 0x00001004 /* This is what we can do with the Zilogs. */ #define B76800 0x00001005 +/* This is what we can do with the SAB82532. */ +#define B153600 0x00001006 +#define B307200 0x00001007 +#define B614400 0x00001008 +#define B921600 0x00001009 +#define B1843200 0x0000100a #define CIBAUD 0x100f0000 /* input baud rate (not used) */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/ttable.h linux/include/asm-sparc64/ttable.h --- v2.1.50/linux/include/asm-sparc64/ttable.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/ttable.h Sat Aug 16 09:51:10 1997 @@ -0,0 +1,320 @@ +/* $Id: ttable.h,v 1.2 1997/08/09 09:03:36 davem Exp $ */ +#ifndef _SPARC64_TTABLE_H +#define _SPARC64_TTABLE_H + +#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop; + +/* We need a "cleaned" instruction... */ +#define CLEAN_WINDOW \ + rdpr %cleanwin, %l0; add %l0, 1, %l0; \ + wrpr %l0, 0x0, %cleanwin; \ + clr %o0; clr %o1; clr %o2; clr %o3; \ + clr %o4; clr %o5; clr %o6; clr %o7; \ + clr %l0; clr %l1; clr %l2; clr %l3; \ + clr %l4; clr %l5; clr %l6; clr %l7; \ + retry; \ + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; + +#define TRAP(routine) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; \ + nop; + +#define TRAP_NOSAVE(routine) \ + ba,pt %xcc, routine; \ + nop; \ + nop; nop; nop; nop; nop; nop; + +#define TRAPTL1(routine) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etraptl1; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; \ + nop; + +#define TRAP_ARG(routine, arg) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + call routine; \ + mov arg, %o1; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define TRAPTL1_ARG(routine, arg) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etraptl1; \ +109: or %g7, %lo(109b), %g7; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + call routine; \ + mov arg, %o1; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define SYSCALL_TRAP(routine, systbl) \ + sethi %hi(109f), %g7; \ + ba,pt %xcc, etrap; \ +109: or %g7, %lo(109b), %g7; \ + call routine; \ + sethi %hi(systbl), %l7; \ + nop; nop; nop; + +#define ACCESS_EXCEPTION_TRAP(routine) \ + rdpr %pstate, %g1; \ + wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ + ba,pt %xcc, etrap; \ + rd %pc, %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define ACCESS_EXCEPTION_TRAPTL1(routine) \ + rdpr %pstate, %g1; \ + wrpr %g1, PSTATE_MG|PSTATE_AG, %pstate; \ + ba,pt %xcc, etraptl1; \ + rd %pc, %g7; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + ba,pt %xcc, rtrap; \ + clr %l6; + +#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sunos_sys_table) +#define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table32) +#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64) +#define GETCC_TRAP TRAP(getcc) +#define SETCC_TRAP TRAP(setcc) +/* FIXME: Write these actually */ +#define NETBSD_SYSCALL_TRAP TRAP(netbsd_syscall) +#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall) +#define BREAKPOINT_TRAP TRAP(breakpoint_trap) +#define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl) + +#define TRAP_IRQ(routine, level) \ + rdpr %pil, %g2; \ + wrpr %g0, 15, %pil; \ + b,pt %xcc, etrap_irq; \ + rd %pc, %g7; \ + mov level, %o0; \ + call routine; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o1; \ + ba,a,pt %xcc, rtrap_clr_l6; + +#ifdef __SMP__ +#define TRAP_TICK \ + rdpr %pil, %g2; \ + wrpr %g0, 15, %pil; \ + b,pt %xcc, etrap_irq; \ + rd %pc, %g7; \ + call smp_percpu_timer_interrupt; \ + add %sp, STACK_BIAS + REGWIN_SZ, %o0; \ + b,pt %xcc, rtrap; \ + clr %l6; +#else +#define TRAP_TICK TRAP_IRQ(handler_irq, 14) +#endif + +#define TRAP_IVEC TRAP_NOSAVE(do_ivec) + +#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl) + +#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl) + +#define FLUSH_WINDOW_TRAP \ + ba,pt %xcc, etrap; \ + rd %pc, %g7; \ + flushw; \ + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1; \ + add %l1, 4, %l2; \ + stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]; \ + ba,pt %xcc, rtrap_clr_l6; \ + stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]; + +/* Before touching these macros, you owe it to yourself to go and + * see how arch/sparc64/kernel/winfixup.S works... -DaveM + */ + +/* Normal kernel spill */ +#define SPILL_0_NORMAL \ + stx %l0, [%sp + STACK_BIAS + 0x00]; \ + stx %l1, [%sp + STACK_BIAS + 0x08]; \ + stx %l2, [%sp + STACK_BIAS + 0x10]; \ + stx %l3, [%sp + STACK_BIAS + 0x18]; \ + stx %l4, [%sp + STACK_BIAS + 0x20]; \ + stx %l5, [%sp + STACK_BIAS + 0x28]; \ + stx %l6, [%sp + STACK_BIAS + 0x30]; \ + stx %l7, [%sp + STACK_BIAS + 0x38]; \ + stx %i0, [%sp + STACK_BIAS + 0x40]; \ + stx %i1, [%sp + STACK_BIAS + 0x48]; \ + stx %i2, [%sp + STACK_BIAS + 0x50]; \ + stx %i3, [%sp + STACK_BIAS + 0x58]; \ + stx %i4, [%sp + STACK_BIAS + 0x60]; \ + stx %i5, [%sp + STACK_BIAS + 0x68]; \ + stx %i6, [%sp + STACK_BIAS + 0x70]; \ + stx %i7, [%sp + STACK_BIAS + 0x78]; \ + saved; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; nop; nop; + +/* Normal 64bit spill */ +#define SPILL_1_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + stxa %l0, [%sp + STACK_BIAS + 0x00] %asi; \ + stxa %l1, [%sp + STACK_BIAS + 0x08] %asi; \ + stxa %l2, [%sp + STACK_BIAS + 0x10] %asi; \ + stxa %l3, [%sp + STACK_BIAS + 0x18] %asi; \ + stxa %l4, [%sp + STACK_BIAS + 0x20] %asi; \ + stxa %l5, [%sp + STACK_BIAS + 0x28] %asi; \ + stxa %l6, [%sp + STACK_BIAS + 0x30] %asi; \ + stxa %l7, [%sp + STACK_BIAS + 0x38] %asi; \ + stxa %i0, [%sp + STACK_BIAS + 0x40] %asi; \ + stxa %i1, [%sp + STACK_BIAS + 0x48] %asi; \ + stxa %i2, [%sp + STACK_BIAS + 0x50] %asi; \ + stxa %i3, [%sp + STACK_BIAS + 0x58] %asi; \ + stxa %i4, [%sp + STACK_BIAS + 0x60] %asi; \ + stxa %i5, [%sp + STACK_BIAS + 0x68] %asi; \ + stxa %i6, [%sp + STACK_BIAS + 0x70] %asi; \ + stxa %i7, [%sp + STACK_BIAS + 0x78] %asi; \ + saved; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; \ + b,a,pt %xcc, spill_fixup_mna; \ + b,a,pt %xcc, spill_fixup; + +/* Normal 32bit spill */ +#define SPILL_2_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + srl %sp, 0, %sp; \ + stwa %l0, [%sp + 0x00] %asi; \ + stwa %l1, [%sp + 0x04] %asi; \ + stwa %l2, [%sp + 0x08] %asi; \ + stwa %l3, [%sp + 0x0c] %asi; \ + stwa %l4, [%sp + 0x10] %asi; \ + stwa %l5, [%sp + 0x14] %asi; \ + stwa %l6, [%sp + 0x18] %asi; \ + stwa %l7, [%sp + 0x1c] %asi; \ + stwa %i0, [%sp + 0x20] %asi; \ + stwa %i1, [%sp + 0x24] %asi; \ + stwa %i2, [%sp + 0x28] %asi; \ + stwa %i3, [%sp + 0x2c] %asi; \ + stwa %i4, [%sp + 0x30] %asi; \ + stwa %i5, [%sp + 0x34] %asi; \ + stwa %i6, [%sp + 0x38] %asi; \ + stwa %i7, [%sp + 0x3c] %asi; \ + saved; retry; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; \ + b,a,pt %xcc, spill_fixup_mna; \ + b,a,pt %xcc, spill_fixup; + +#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP) +#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP) +#define SPILL_3_NORMAL SPILL_0_NORMAL +#define SPILL_4_NORMAL SPILL_0_NORMAL +#define SPILL_5_NORMAL SPILL_0_NORMAL +#define SPILL_6_NORMAL SPILL_0_NORMAL +#define SPILL_7_NORMAL SPILL_0_NORMAL + +#define SPILL_0_OTHER SPILL_0_NORMAL +#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS) +#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS) +#define SPILL_3_OTHER SPILL_3_NORMAL +#define SPILL_4_OTHER SPILL_4_NORMAL +#define SPILL_5_OTHER SPILL_5_NORMAL +#define SPILL_6_OTHER SPILL_6_NORMAL +#define SPILL_7_OTHER SPILL_7_NORMAL + +/* Normal kernel fill */ +#define FILL_0_NORMAL \ + ldx [%sp + STACK_BIAS + 0x00], %l0; \ + ldx [%sp + STACK_BIAS + 0x08], %l1; \ + ldx [%sp + STACK_BIAS + 0x10], %l2; \ + ldx [%sp + STACK_BIAS + 0x18], %l3; \ + ldx [%sp + STACK_BIAS + 0x20], %l4; \ + ldx [%sp + STACK_BIAS + 0x28], %l5; \ + ldx [%sp + STACK_BIAS + 0x30], %l6; \ + ldx [%sp + STACK_BIAS + 0x38], %l7; \ + ldx [%sp + STACK_BIAS + 0x40], %i0; \ + ldx [%sp + STACK_BIAS + 0x48], %i1; \ + ldx [%sp + STACK_BIAS + 0x50], %i2; \ + ldx [%sp + STACK_BIAS + 0x58], %i3; \ + ldx [%sp + STACK_BIAS + 0x60], %i4; \ + ldx [%sp + STACK_BIAS + 0x68], %i5; \ + ldx [%sp + STACK_BIAS + 0x70], %i6; \ + ldx [%sp + STACK_BIAS + 0x78], %i7; \ + restored; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; nop; nop; + +/* Normal 64bit fill */ +#define FILL_1_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + ldxa [%sp + STACK_BIAS + 0x00] %asi, %l0; \ + ldxa [%sp + STACK_BIAS + 0x08] %asi, %l1; \ + ldxa [%sp + STACK_BIAS + 0x10] %asi, %l2; \ + ldxa [%sp + STACK_BIAS + 0x18] %asi, %l3; \ + ldxa [%sp + STACK_BIAS + 0x20] %asi, %l4; \ + ldxa [%sp + STACK_BIAS + 0x28] %asi, %l5; \ + ldxa [%sp + STACK_BIAS + 0x30] %asi, %l6; \ + ldxa [%sp + STACK_BIAS + 0x38] %asi, %l7; \ + ldxa [%sp + STACK_BIAS + 0x40] %asi, %i0; \ + ldxa [%sp + STACK_BIAS + 0x48] %asi, %i1; \ + ldxa [%sp + STACK_BIAS + 0x50] %asi, %i2; \ + ldxa [%sp + STACK_BIAS + 0x58] %asi, %i3; \ + ldxa [%sp + STACK_BIAS + 0x60] %asi, %i4; \ + ldxa [%sp + STACK_BIAS + 0x68] %asi, %i5; \ + ldxa [%sp + STACK_BIAS + 0x70] %asi, %i6; \ + ldxa [%sp + STACK_BIAS + 0x78] %asi, %i7; \ + restored; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; \ + b,a,pt %xcc, fill_fixup_mna; \ + b,a,pt %xcc, fill_fixup; + +/* Normal 32bit fill */ +#define FILL_2_GENERIC(xxx) \ + wr %g0, xxx, %asi; \ + srl %sp, 0, %sp; \ + lduwa [%sp + 0x00] %asi, %l0; \ + lduwa [%sp + 0x04] %asi, %l1; \ + lduwa [%sp + 0x08] %asi, %l2; \ + lduwa [%sp + 0x0c] %asi, %l3; \ + lduwa [%sp + 0x10] %asi, %l4; \ + lduwa [%sp + 0x14] %asi, %l5; \ + lduwa [%sp + 0x18] %asi, %l6; \ + lduwa [%sp + 0x1c] %asi, %l7; \ + lduwa [%sp + 0x20] %asi, %i0; \ + lduwa [%sp + 0x24] %asi, %i1; \ + lduwa [%sp + 0x28] %asi, %i2; \ + lduwa [%sp + 0x2c] %asi, %i3; \ + lduwa [%sp + 0x30] %asi, %i4; \ + lduwa [%sp + 0x34] %asi, %i5; \ + lduwa [%sp + 0x38] %asi, %i6; \ + lduwa [%sp + 0x3c] %asi, %i7; \ + restored; retry; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; nop; \ + b,a,pt %xcc, fill_fixup_mna; \ + b,a,pt %xcc, fill_fixup; + +#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP) +#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP) +#define FILL_3_NORMAL FILL_0_NORMAL +#define FILL_4_NORMAL FILL_0_NORMAL +#define FILL_5_NORMAL FILL_0_NORMAL +#define FILL_6_NORMAL FILL_0_NORMAL +#define FILL_7_NORMAL FILL_0_NORMAL + +#define FILL_0_OTHER FILL_0_NORMAL +#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS) +#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS) +#define FILL_3_OTHER FILL_3_NORMAL +#define FILL_4_OTHER FILL_4_NORMAL +#define FILL_5_OTHER FILL_5_NORMAL +#define FILL_6_OTHER FILL_6_NORMAL +#define FILL_7_OTHER FILL_7_NORMAL + +#endif /* !(_SPARC64_TTABLE_H) */ diff -u --recursive --new-file v2.1.50/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h --- v2.1.50/linux/include/asm-sparc64/uaccess.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/uaccess.h Sat Aug 16 09:51:10 1997 @@ -1,4 +1,4 @@ -/* $Id: uaccess.h,v 1.20 1997/07/13 18:23:45 davem Exp $ */ +/* $Id: uaccess.h,v 1.21 1997/07/31 07:37:25 davem Exp $ */ #ifndef _ASM_UACCESS_H #define _ASM_UACCESS_H @@ -30,8 +30,11 @@ #define get_fs() (current->tss.current_ds) #define get_ds() (KERNEL_DS) + +extern spinlock_t scheduler_lock; + #define set_fs(val) \ -do { \ +do { spin_lock(&scheduler_lock); \ current->tss.current_ds = (val); \ if ((val) == KERNEL_DS) { \ flushw_user (); \ @@ -41,6 +44,7 @@ } \ spitfire_set_secondary_context(current->tss.ctx); \ __asm__ __volatile__("flush %g6"); \ + spin_unlock(&scheduler_lock); \ } while(0) #define __user_ok(addr,size) 1 diff -u --recursive --new-file v2.1.50/linux/include/linux/blk.h linux/include/linux/blk.h --- v2.1.50/linux/include/linux/blk.h Mon Jul 7 16:02:14 1997 +++ linux/include/linux/blk.h Mon Aug 18 17:09:22 1997 @@ -97,6 +97,9 @@ #ifdef CONFIG_AMIGA_Z2RAM extern int z2_init(void); #endif +#ifdef CONFIG_MAC_FLOPPY +extern int swim3_init(void); +#endif extern void set_device_ro(kdev_t dev,int flag); void add_blkdev_randomness(int major); diff -u --recursive --new-file v2.1.50/linux/include/linux/dcache.h linux/include/linux/dcache.h --- v2.1.50/linux/include/linux/dcache.h Thu Aug 14 20:49:17 1997 +++ linux/include/linux/dcache.h Thu Aug 14 21:40:57 1997 @@ -97,7 +97,6 @@ extern void d_delete(struct dentry *); /* allocate/de-allocate */ -extern void d_free(struct dentry *); extern struct dentry * d_alloc(struct dentry * parent, const struct qstr *name); extern void shrink_dcache(void); extern int d_invalidate(struct dentry *); diff -u --recursive --new-file v2.1.50/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.50/linux/include/linux/fs.h Thu Aug 14 20:49:17 1997 +++ linux/include/linux/fs.h Mon Aug 18 17:09:10 1997 @@ -93,7 +93,7 @@ /* * Flags that can be altered by MS_REMOUNT */ -#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK) +#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK|MS_NOATIME) /* * Magic mount flag number. Has to be or-ed to the flag values. diff -u --recursive --new-file v2.1.50/linux/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h --- v2.1.50/linux/include/linux/nfsd/nfsfh.h Sun Jul 27 12:11:01 1997 +++ linux/include/linux/nfsd/nfsfh.h Mon Aug 18 17:10:46 1997 @@ -137,6 +137,7 @@ if (fhp->fh_dverified) { fh_unlock(fhp); dput(fhp->fh_handle.fh_dentry); + fhp->fh_dverified = 0; } } #else @@ -159,6 +160,7 @@ } else { fh_unlock(fhp); dput(dentry); + fhp->fh_dverified = 0; } } #endif diff -u --recursive --new-file v2.1.50/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.50/linux/include/linux/proc_fs.h Mon Aug 4 16:25:40 1997 +++ linux/include/linux/proc_fs.h Mon Aug 18 17:09:11 1997 @@ -51,7 +51,8 @@ PROC_HARDWARE, PROC_SLABINFO, PROC_PARPORT, - PROC_OMIRR /* whether enabled or not */ + PROC_OMIRR, /* whether enabled or not */ + PROC_PPC_HTAB }; enum pid_directory_inos { @@ -181,6 +182,8 @@ PROC_SCSI_GVP11, PROC_SCSI_ATARI, PROC_SCSI_IDESCSI, + PROC_SCSI_MESH, + PROC_SCSI_53C94, PROC_SCSI_SCSI_DEBUG, PROC_SCSI_NOT_PRESENT, PROC_SCSI_FILE, /* I'm assuming here that we */ @@ -362,6 +365,7 @@ extern struct inode_operations proc_ringbuf_inode_operations; #endif extern struct inode_operations proc_omirr_inode_operations; +extern struct inode_operations proc_ppc_htab_inode_operations; #endif @@ -378,3 +382,8 @@ extern void proc_tty_init(void); extern void proc_tty_register_driver(struct tty_driver *driver); extern void proc_tty_unregister_driver(struct tty_driver *driver); + +/* + * proc_devtree.c + */ +extern void proc_device_tree_init(void); diff -u --recursive --new-file v2.1.50/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.50/linux/include/linux/tty.h Mon Jul 7 16:02:03 1997 +++ linux/include/linux/tty.h Mon Aug 18 17:09:10 1997 @@ -74,6 +74,8 @@ #define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */ +#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */ + /* * This character is the same as _POSIX_VDISABLE: it cannot be used as * a c_cc[] character, but indicates that a particular special character diff -u --recursive --new-file v2.1.50/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.50/linux/kernel/fork.c Thu Aug 14 20:49:17 1997 +++ linux/kernel/fork.c Mon Aug 18 16:13:34 1997 @@ -206,6 +206,7 @@ static inline int dup_mmap(struct mm_struct * mm) { struct vm_area_struct * mpnt, *tmp, **pprev; + int retval; mm->mmap = mm->mmap_cache = NULL; flush_cache_mm(current->mm); @@ -213,19 +214,17 @@ for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { struct dentry *dentry; + retval = -ENOMEM; tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if (!tmp) { - exit_mmap(mm); - flush_tlb_mm(current->mm); - return -ENOMEM; - } + if (!tmp) + goto fail_nomem; *tmp = *mpnt; tmp->vm_flags &= ~VM_LOCKED; tmp->vm_mm = mm; tmp->vm_next = NULL; dentry = tmp->vm_dentry; if (dentry) { - dentry->d_count++; + dget(dentry); if (tmp->vm_flags & VM_DENYWRITE) dentry->d_inode->i_writecount--; @@ -236,60 +235,79 @@ mpnt->vm_next_share = tmp; tmp->vm_pprev_share = &mpnt->vm_next_share; } - if (copy_page_range(mm, current->mm, tmp)) { - exit_mmap(mm); - flush_tlb_mm(current->mm); - return -ENOMEM; - } - if (tmp->vm_ops && tmp->vm_ops->open) + + /* Copy the pages, but defer checking for errors */ + retval = copy_page_range(mm, current->mm, tmp); + if (!retval && tmp->vm_ops && tmp->vm_ops->open) tmp->vm_ops->open(tmp); - /* Ok, finally safe to link it in. */ + /* + * Link in the new vma even if an error occurred, + * so that exit_mmap() can clean up the mess. + */ if((tmp->vm_next = *pprev) != NULL) (*pprev)->vm_pprev = &tmp->vm_next; *pprev = tmp; tmp->vm_pprev = pprev; pprev = &tmp->vm_next; + if (retval) + goto fail_nomem; } flush_tlb_mm(current->mm); return 0; + +fail_nomem: + exit_mmap(mm); + flush_tlb_mm(current->mm); + return retval; } static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk) { - if (!(clone_flags & CLONE_VM)) { - struct mm_struct * mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); - if (!mm) - return -1; - *mm = *current->mm; - init_new_context(mm); - mm->count = 1; - mm->def_flags = 0; - mm->mmap_sem = MUTEX; - - /* It has not run yet, so cannot be present in anyone's - * cache or tlb. - */ - mm->cpu_vm_mask = 0; + struct mm_struct * mm; + int retval; - tsk->mm = mm; - tsk->min_flt = tsk->maj_flt = 0; - tsk->cmin_flt = tsk->cmaj_flt = 0; - tsk->nswap = tsk->cnswap = 0; - if (new_page_tables(tsk)) - goto free_mm; - if (dup_mmap(mm)) { - free_page_tables(mm); -free_mm: - kmem_cache_free(mm_cachep, mm); - return -1; - } + if (clone_flags & CLONE_VM) { + current->mm->count++; + SET_PAGE_DIR(tsk, current->mm->pgd); return 0; } - current->mm->count++; - SET_PAGE_DIR(tsk, current->mm->pgd); + + retval = -ENOMEM; + mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); + if (!mm) + goto fail_nomem; + *mm = *current->mm; + init_new_context(mm); + mm->count = 1; + mm->def_flags = 0; + mm->mmap_sem = MUTEX; + + /* It has not run yet, so cannot be present in anyone's + * cache or tlb. + */ + mm->cpu_vm_mask = 0; + + tsk->mm = mm; + tsk->min_flt = tsk->maj_flt = 0; + tsk->cmin_flt = tsk->cmaj_flt = 0; + tsk->nswap = tsk->cnswap = 0; + retval = new_page_tables(tsk); + if (retval) + goto free_mm; + retval = dup_mmap(mm); + if (retval) + goto free_pt; return 0; + +free_pt: + free_page_tables(mm); +free_mm: + tsk->mm = NULL; + kmem_cache_free(mm_cachep, mm); +fail_nomem: + return retval; } static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk) @@ -478,9 +496,9 @@ bad_fork_cleanup_sighand: exit_sighand(p); bad_fork_cleanup_fs: - exit_fs(p); + exit_fs(p); /* blocking */ bad_fork_cleanup_files: - exit_files(p); + exit_files(p); /* blocking */ bad_fork_cleanup: charge_uid(current, -1); if (p->exec_domain && p->exec_domain->module) diff -u --recursive --new-file v2.1.50/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.50/linux/kernel/ksyms.c Thu Aug 14 20:49:17 1997 +++ linux/kernel/ksyms.c Fri Aug 15 15:34:49 1997 @@ -67,7 +67,6 @@ #include #ifdef __SMP__ #include -#include #endif extern char *get_options(char *str, int *ints); @@ -282,7 +281,6 @@ /* Various random spinlocks we want to export */ EXPORT_SYMBOL(tqueue_lock); EXPORT_SYMBOL(waitqueue_lock); -EXPORT_SYMBOL(lk_lockmsg); #endif /* autoirq from drivers/net/auto_irq.c */ diff -u --recursive --new-file v2.1.50/linux/mm/memory.c linux/mm/memory.c --- v2.1.50/linux/mm/memory.c Sun Jun 29 10:48:37 1997 +++ linux/mm/memory.c Mon Aug 18 13:06:50 1997 @@ -291,19 +291,20 @@ return error; } -static inline void free_pte(pte_t page) +/* + * Return indicates whether a page was freed so caller can adjust rss + */ +static inline int free_pte(pte_t page) { if (pte_present(page)) { unsigned long addr = pte_page(page); if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr))) - return; + return 0; free_page(addr); - if (current->mm->rss <= 0) - return; - current->mm->rss--; - return; + return 1; } swap_free(pte_val(page)); + return 0; } static inline void forget_pte(pte_t page) @@ -314,22 +315,24 @@ } } -static inline void zap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size) +static inline int zap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size) { pte_t * pte; + int freed; if (pmd_none(*pmd)) - return; + return 0; if (pmd_bad(*pmd)) { printk("zap_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd)); pmd_clear(pmd); - return; + return 0; } pte = pte_offset(pmd, address); address &= ~PMD_MASK; if (address + size > PMD_SIZE) size = PMD_SIZE - address; size >>= PAGE_SHIFT; + freed = 0; for (;;) { pte_t page; if (!size) @@ -340,32 +343,36 @@ if (pte_none(page)) continue; pte_clear(pte-1); - free_pte(page); + freed += free_pte(page); } + return freed; } -static inline void zap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size) +static inline int zap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size) { pmd_t * pmd; unsigned long end; + int freed; if (pgd_none(*dir)) - return; + return 0; if (pgd_bad(*dir)) { printk("zap_pmd_range: bad pgd (%08lx)\n", pgd_val(*dir)); pgd_clear(dir); - return; + return 0; } pmd = pmd_offset(dir, address); address &= ~PGDIR_MASK; end = address + size; if (end > PGDIR_SIZE) end = PGDIR_SIZE; + freed = 0; do { - zap_pte_range(pmd, address, end - address); + freed += zap_pte_range(pmd, address, end - address); address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); + return freed; } /* @@ -375,12 +382,21 @@ { pgd_t * dir; unsigned long end = address + size; + int freed = 0; dir = pgd_offset(mm, address); while (address < end) { - zap_pmd_range(dir, address, end - address); + freed += zap_pmd_range(dir, address, end - address); address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; + } + /* + * Update rss for the mm_struct (not necessarily current->mm) + */ + if (mm->rss > 0) { + mm->rss -= freed; + if (mm->rss < 0) + mm->rss = 0; } } diff -u --recursive --new-file v2.1.50/linux/mm/mmap.c linux/mm/mmap.c --- v2.1.50/linux/mm/mmap.c Thu Jul 17 10:06:09 1997 +++ linux/mm/mmap.c Mon Aug 18 13:16:18 1997 @@ -373,10 +373,12 @@ * Unmapping between to intermediate points, making a hole. * * Case 4 involves the creation of 2 new areas, for each side of - * the hole. + * the hole. If possible, we reuse the existing area rather than + * allocate a new one, and the return indicates whether the old + * area was reused. */ -static void unmap_fixup(struct vm_area_struct *area, - unsigned long addr, size_t len) +static int unmap_fixup(struct vm_area_struct *area, unsigned long addr, + size_t len, struct vm_area_struct **extra) { struct vm_area_struct *mpnt; unsigned long end = addr + len; @@ -391,7 +393,7 @@ area->vm_ops->close(area); if (area->vm_dentry) dput(area->vm_dentry); - return; + return 0; } /* Work out to one of the ends. */ @@ -403,17 +405,16 @@ } else { /* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */ /* Add end mapping -- leave beginning for below */ - mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + mpnt = *extra; + *extra = NULL; - if (!mpnt) - return; mpnt->vm_mm = area->vm_mm; mpnt->vm_start = end; mpnt->vm_end = area->vm_end; mpnt->vm_page_prot = area->vm_page_prot; mpnt->vm_flags = area->vm_flags; mpnt->vm_ops = area->vm_ops; - mpnt->vm_offset += (end - area->vm_start); + mpnt->vm_offset = area->vm_offset + (end - area->vm_start); mpnt->vm_dentry = dget(area->vm_dentry); if (mpnt->vm_ops && mpnt->vm_ops->open) mpnt->vm_ops->open(mpnt); @@ -421,18 +422,18 @@ insert_vm_struct(current->mm, mpnt); } - /* Construct whatever mapping is needed. */ - mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if (!mpnt) - return; - *mpnt = *area; - if (mpnt->vm_ops && mpnt->vm_ops->open) - mpnt->vm_ops->open(mpnt); + /* Close the current area ... */ if (area->vm_ops && area->vm_ops->close) { + end = area->vm_end; /* save new end */ area->vm_end = area->vm_start; area->vm_ops->close(area); + area->vm_end = end; } - insert_vm_struct(current->mm, mpnt); + /* ... then reopen and reinsert. */ + if (area->vm_ops && area->vm_ops->open) + area->vm_ops->open(area); + insert_vm_struct(current->mm, area); + return 1; } asmlinkage int sys_munmap(unsigned long addr, size_t len) @@ -452,7 +453,8 @@ */ int do_munmap(unsigned long addr, size_t len) { - struct vm_area_struct *mpnt, *next, *free; + struct vm_area_struct *mpnt, *next, *free, *extra; + int freed; if ((addr & ~PAGE_MASK) || addr > TASK_SIZE || len > TASK_SIZE-addr) return -EINVAL; @@ -471,6 +473,14 @@ if (!mpnt) return 0; + /* + * We may need one additional vma to fix up the mappings ... + * and this is the last chance for an easy error exit. + */ + extra = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (!extra) + return -ENOMEM; + next = mpnt->vm_next; /* we have mpnt->vm_next = next and addr < mpnt->vm_end */ @@ -486,19 +496,18 @@ free = mpnt; mpnt = next; } - if (free == NULL) - return 0; /* Ok - we have the memory areas we should free on the 'free' list, * so release them, and unmap the page range.. * If the one of the segments is only being partially unmapped, * it will put new vm_area_struct(s) into the address space. */ - do { + freed = 0; + while ((mpnt = free) != NULL) { unsigned long st, end, size; - mpnt = free; free = free->vm_next; + freed = 1; remove_shared_vm_struct(mpnt); @@ -514,12 +523,19 @@ zap_page_range(current->mm, st, size); flush_tlb_range(current->mm, st, end); - unmap_fixup(mpnt, st, size); + /* + * Fix the mapping, and free the old area if it wasn't reused. + */ + if (!unmap_fixup(mpnt, st, size, &extra)) + kmem_cache_free(vm_area_cachep, mpnt); + } - kmem_cache_free(vm_area_cachep, mpnt); - } while (free); + /* Release the extra vma struct if it wasn't used */ + if (extra) + kmem_cache_free(vm_area_cachep, extra); - current->mm->mmap_cache = NULL; /* Kill the cache. */ + if (freed) + current->mm->mmap_cache = NULL; /* Kill the cache. */ return 0; } diff -u --recursive --new-file v2.1.50/linux/net/ipv4/fib.c linux/net/ipv4/fib.c --- v2.1.50/linux/net/ipv4/fib.c Mon Jun 16 16:36:01 1997 +++ linux/net/ipv4/fib.c Fri Aug 15 12:52:03 1997 @@ -2039,7 +2039,7 @@ fib_class_get_info }); proc_net_register(&(struct proc_dir_entry) { - PROC_NET_RTRULES, 8, "rt_local", + PROC_NET_RTLOCAL, 8, "rt_local", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, fib_local_get_info diff -u --recursive --new-file v2.1.50/linux/net/socket.c linux/net/socket.c --- v2.1.50/linux/net/socket.c Sun Jul 20 20:41:59 1997 +++ linux/net/socket.c Fri Aug 15 14:59:49 1997 @@ -648,28 +648,25 @@ asmlinkage int sys_socket(int family, int type, int protocol) { - int fd, err; + int retval; struct socket *sock; lock_kernel(); - if ((err = sock_create(family, type, protocol, &sock)) < 0) + retval = sock_create(family, type, protocol, &sock); + if (retval < 0) goto out; - if ((fd = get_fd(sock->inode)) < 0) - { + retval = get_fd(sock->inode); + if (retval < 0) { sock_release(sock); - err = -EINVAL; - } - else - { - sock->file = current->files->fd[fd]; - err = fd; + goto out; } + sock->file = current->files->fd[retval]; out: unlock_kernel(); - return err; + return retval; } /*