diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/CREDITS linux.ac/CREDITS --- linux-2.4.0/CREDITS Sun Dec 31 17:27:57 2000 +++ linux.ac/CREDITS Fri Jan 5 14:27:47 2001 @@ -957,6 +957,8 @@ N: Hans Grobler E: grobh@sun.ac.za D: Various AX.25/ROSE/NETROM + hamradio driver patches +D: Various X.25/LABP + driver patches +D: Misc kernel fixes and updates S: Department of Electronic Engineering S: University of Stellenbosch S: Stellenbosch, Western Cape diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/Configure.help linux.ac/Documentation/Configure.help --- linux-2.4.0/Documentation/Configure.help Thu Jan 4 21:00:55 2001 +++ linux.ac/Documentation/Configure.help Fri Jan 5 13:43:08 2001 @@ -268,6 +268,11 @@ Most normal users won't need the RAM disk functionality, and can thus say N here. +Default RAM disk size +CONFIG_BLK_DEV_RAM_SIZE + The default value is 4096. Only change this if you know what are + you doing. If you are using IBM S/390, then set this to 8192. + Initial RAM disk (initrd) support CONFIG_BLK_DEV_INITRD The initial RAM disk is a RAM disk that is loaded by the boot loader @@ -868,9 +873,9 @@ This is a driver for the OPTi 82C621 EIDE controller. Please read the comments at the top of drivers/ide/opti621.c. -ServerWorks OSB4 chipset support (EXPERIMENTAL) +ServerWorks OSB4 chipset support CONFIG_BLK_DEV_OSB4 - This driver adds PIO/DMA support for the Serverworks OSB4 chipset + This driver adds PIO/(U)DMA support for the ServerWorks OSB4 chipset. Intel PIIXn chipsets support CONFIG_BLK_DEV_PIIX @@ -898,7 +903,7 @@ If unsure, say N. -PROMISE PDC20246/PDC20262/PDC20267 support +PROMISE PDC20246/PDC20262/PDC20265/PDC20267 support CONFIG_BLK_DEV_PDC202XX Promise Ultra33 or PDC20246 Promise Ultra66 or PDC20262 @@ -971,13 +976,11 @@ VIA82CXXX chipset support CONFIG_BLK_DEV_VIA82CXXX - This allows you to configure your chipset for a better use while - running (U)DMA: it will allow you to enable efficiently the second - channel dma usage, as it may not be set by BIOS. It allows you to - pass a kernel command line at boot time in order to set fifo - config. If no command line is provided, it will try to set fifo + This allows you to to configure your chipset for a better use while + running PIO/(U)DMA, it will allow you to enable efficiently the second + channel dma usage, as it may not be set by BIOS. It will try to set fifo configuration at its best. It will allow you to get information from - /proc/ide/via provided you enabled "proc" support. + /proc/ide/via provided you enabled "/proc file system" support. Please read the comments at the top of drivers/ide/via82cxxx.c @@ -986,12 +989,6 @@ If unsure, say N. -VIA82CXXX Tuning support (WIP) -CONFIG_VIA82CXXX_TUNING - Please read the comments at the top of drivers/ide/via82cxxx.c - - If unsure, say N. - Other IDE chipset support CONFIG_IDE_CHIPSETS Say Y here if you want to include enhanced support for various IDE @@ -2397,12 +2394,15 @@ the GLX component for XFree86 3.3.6, which can be downloaded from http://utah-glx.sourceforge.net/ . -ALI M1541 support +ALI chipset support CONFIG_AGP_ALI This option gives you AGP support for the GLX component of the - XFree86 4.x on the ALi M1541 chipset. + XFree86 4.x on the following ALi chipsets. The supported chipsets + include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. + For ALi-chipset question, ALi welcome you refer to + http://www.ali.com.tw/eng/support/index.shtml - This chipset can do AGP 1x and 2x, but note that there is an + The M1541 chipset can do AGP 1x and 2x, but note that there is an acknowledged incompatibility with Matrox G200 cards. Due to timing issues, this chipset cannot do AGP 2x with the G200. This is a hardware limitation. AGP 1x seems to be fine, though. @@ -4188,11 +4188,10 @@ 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://threepio.hitchcock.org/cgi-bin/faq/netatalk/faq.pl on the WWW - for details. EtherTalk is the name used for AppleTalk over Ethernet - and the cheaper and slower LocalTalk is AppleTalk over a proprietary - Apple network using serial links. EtherTalk and LocalTalk are fully - supported by Linux. + http://www.zettabyte.net/netatalk/ on the WWW for details. EtherTalk + is the name used for AppleTalk over Ethernet and the cheaper and + slower LocalTalk is AppleTalk over a proprietary Apple network using + serial links. EtherTalk and LocalTalk are fully supported by Linux. General information about how to connect Linux, Windows machines and Macs is on the WWW at http://www.eats.com/linux_mac_win.html . The @@ -4203,8 +4202,10 @@ This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called appletalk.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. I hear that - the GNU boycott of Apple is over, so even politically correct people + module, say M here and read Documentation/modules.txt. You almost + certainly want to compile it as a module so you can restart your + AppleTalk stack without rebooting your machine. I hear that the + GNU boycott of Apple is over, so even politically correct people are allowed to say Y here. AppleTalk-IP driver support @@ -4958,6 +4959,15 @@ Note that extended debugging may create certain race conditions itself. Enable this ONLY if you suspect problems with the driver. +Fujitsu FireStream (FS50/FS155) +CONFIG_ATM_FIRESTREAM + Driver for the Fujitsu FireStream 155 (MB86697) and + FireStream 50 (MB86695) ATM PCI chips. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called firestream.o. + Enable usec resolution timestamps CONFIG_ATM_ZATM_EXACT_TS The uPD98401 SAR chip supports a high-resolution timer (approx. 30 @@ -5178,6 +5188,117 @@ the performances of the driver, and the size of your syslog files! Keep the debugging level to 0 during normal operations. +Fusion MPT device support +CONFIG_FUSION + LSI Logic Fusion(TM) Message Passing Technology (MPT) device support + provides high performance SCSI host initiator, and LAN [1] interface + services to a host system. The Fusion architecture is capable of + duplexing these protocols on high-speed Fibre Channel + (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320) + physical medium. + + [1] LAN is not supported on parallel SCSI medium. + + These drivers require a Fusion MPT compatible PCI adapter installed in + the host system. MPT adapters contain specialized I/O processors + to handle I/O workload, and more importantly to offload this work + from the host CPU(s). + + If you have Fusion MPT hardware and want to use it, you can say + Y or M here to add MPT (base + ScsiHost) drivers. + = build lib (fusion.o), and link [static] into the kernel [2] proper + = compiled as [dynamic] modules [3] named: (mptbase.o, mptscsih.o) + + [2] In order enable capability to boot the linux kernel natively + from a Fusion MPT target device, you MUST answer Y here! + (currently requires CONFIG_BLK_DEV_SD) + [3] This support is also available as a module + ( = code which can be inserted in and removed + from the running kernel whenever you want). + If you want to compile as modules, say M here and read + Documentation/modules.txt. + + If unsure, say N. + + If you say Y or M here you will get a choice of these + additional protocol and support module options: Module Name: + Enhanced SCSI error reporting (isense.o) + Fusion MPT misc device (ioctl) driver (mptctl.o) + Fusion MPT LAN driver (mptlan.o) + + --- + Fusion MPT is trademark of LSI Logic Corporation, and it's architecture + is based on LSI Logic's Message Passing Interface (MPI) specification. + +Fusion MPT enhanced SCSI error reporting [optional] module +CONFIG_FUSION_ISENSE + The isense module (roughly stands for Interpret SENSE data) is + completely optional. It simply provides extra English readable + strings in SCSI Error Report(s) that might be generated from the + Fusion MPT SCSI Host driver, for example when a target device + returns a SCSI check condition on a I/O. Without this module + loaded you might see: + + SCSI Error Report =-=-= (ioc0,scsi5:0) + SCSI_Status=02h (CHECK_CONDITION) + Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 + SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00 + SenseKey=2h (NOT READY); FRU=02h + ASC/ASCQ=29h/00h + + Where otherwise, if this module had been loaded, you would see: + + SCSI Error Report =-=-= (ioc0,scsi5:0) + SCSI_Status=02h (CHECK_CONDITION) + Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)" + SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00 + SenseKey=2h (NOT READY); FRU=02h + ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED" + + Say M for "Enhanced SCSI error reporting" to compile this optional module, + creating a driver named: isense.o + + NOTE: Support for building this feature into the kernel is not + available, due to kernel size considerations. + +Fusion MPT misc device (ioctl) driver [optional] module +CONFIG_FUSION_CTL + The Fusion MPT misc device driver provides specialized control + of MPT adapters via system ioctl calls. Use of ioctl calls to + the MPT driver requires that you create and use a misc device + node ala: + mknod /dev/mptctl c 10 167 + + One use of this ioctl interface is to perform an upgrade (reflash) + of the MPT adapter firmware. Refer to readme file(s) distributed + with the Fusion MPT linux driver for additional details. + + If enabled by saying M to this, a driver named: mptctl.o + will be compiled. + + If unsure whether you really want or need this, say no. + +Fusion MPT LAN driver [optional] +CONFIG_FUSION_LAN + This module supports LAN IP traffic over Fibre Channel port(s) + on Fusion MPT compatible hardware (SYMFC9xx chips). + The physical interface used is defined in RFC 2625. + Please refer to that document for details. + + Installing this driver requires the knowledge to configure and + activate a new network interface, "fc0", using standard Linux tools. + + If enabled by saying M to this, a driver named: mptlan.o + will be compiled. + + If unsure whether you really want or need this, say no. + + NOTES: This feature is NOT available nor supported for linux-2.2.x + kernels. You must be building a linux-2.3.x or linux-2.4.x kernel + in order to configure this option. + Support for building this feature into the linux kernel is not + yet available. + SCSI support? CONFIG_SCSI If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or @@ -8120,7 +8241,7 @@ If you want to compile this as a module, say M and read Documentation/modules.txt. The module will be called i810-tco.o. - + MultiGate Cisco-HDLC and synchronous PPP protocol support CONFIG_COMX_PROTO_PPP Cisco-HDLC and synchronous PPP protocol driver for all MultiGate @@ -8183,6 +8304,49 @@ If you say N, the X.25 support will not be included in the driver (saves about 11 KB of kernel memory). +Generic HDLC driver +CONFIG_HDLC + Say Y to this option if your Linux box contains a WAN card supported + by this driver and you are planning to connect the box to a WAN + ( = Wide Area Network). You will need supporting software from + http://hq.pm.waw.pl/pub/hdlc/. + Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame + Relay, synchronous Point-to-Point Protocol (PPP) and X.25. + + If unsure, say N here. + +Synchronous Point-to-Point Protocol (PPP) +CONFIG_HDLC_PPP + Say Y to this option if you want generic HDLC driver to support + PPP over WAN (Wide Area Network) connections. + + If unsure, say N here. + +CCITT X.25 protocol +CONFIG_HDLC_X25 + Say Y to this option if you want generic HDLC driver to support + X.25 protocol over WAN (Wide Area Network) connections. + + If unsure, say N here. + +SDL RISCom/N2 driver +CONFIG_N2 + This driver is for RISCom/N2 single or dual channel ISA cards + made by SDL Communications Inc. If you have such a card, + say Y here and see http://hq.pm.waw.pl/pub/hdlc/ + + Note that N2csu and N2dds cards are not supported by this driver. + + If unsure, say N here. + +Moxa C101 driver +CONFIG_C101 + This driver is for C101 SuperSync ISA cards made by Moxa + Technologies Co., Ltd. If you have such a card, + say Y here and see http://hq.pm.waw.pl/pub/hdlc/ + + If unsure, say N here. + Ethernet (10 or 100Mbit) CONFIG_NET_ETHERNET Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common @@ -11022,6 +11186,16 @@ (the one containing the directory /) cannot be a module, so saying M could be dangerous. If unsure, say N. +PReP residual data support +CONFIG_PREP_RESIDUAL + Some PReP systems have residual data passed to the kernel by the + firmware. This allows detection of memory size, devices present and + other useful pieces of information. Sometimes this information is not + present or incorrect. + + Unless you expect to boot on a PReP system, there is not need to select + yes. + /proc file system support CONFIG_PROC_FS This is a virtual file system providing information about the status @@ -14336,6 +14510,18 @@ If unsure, say Y. +Yamaha PCI native mode support (EXPERIMENTAL) +CONFIG_SOUND_YMFPCI + This is an experimental driver that uses Yamaha PCI sound cards in + the native mode. You may also want to try another driver, + "Yamaha PCI legacy mode support" under the OSS drivers. + +Yamaha PCI legacy mode support +CONFIG_SOUND_YMPCI + This is a driver for Yamaha PCI sound cards that turns them + to the Sound Blaster compatible mode. You don't need to enable + Sound Blaster support to use it. + ACI mixer (miroPCM12/PCM20) CONFIG_SOUND_ACI_MIXER ACI (Audio Command Interface) is a protocol used to communicate with @@ -14419,6 +14605,11 @@ driver as a module you have to specify the MPU I/O base address with the parameter 'mpu_base=0xNNN'. +C-Media PCI (CMI8338/8378) +CONFIG_SOUND_CMPCI + Say Y or M if you have a PCI sound card using the CMI8338 + or the CMI8378 chip.set. + Creative EMU10K1 based PCI sound cards CONFIG_SOUND_EMU10K1 Say Y or M if you have a PCI sound card using the EMU10K1 @@ -15731,22 +15922,34 @@ Processor Type CONFIG_6xx There are four types of PowerPC chips supported. The more common - types (601, 603, 604, 740, 750), the Motorola embedded versions - (821, 823, 850, 855, 860), the IBM embedded versions (403 and + types (601, 603, 604, 740, 750, 7400), the Motorola embedded versions + (821, 823, 850, 855, 860, 8260), the IBM embedded versions (403 and 405) and the high end 64 bit Power processors (Power 3, Power 4). - Unless you are building a kernel for one of the embedded - processor systems, or a 64 bit IBM RS/6000, choose 6xx. Note that - the kernel runs in 32-bit mode even on 64-bit chips. + Unless you are building a kernel for one of the embedded processor + systems, or a 64 bit IBM RS/6000, choose 6xx. Note that the kernel + runs in 32-bit mode even on 64-bit chips. + +Workarounds for PPC601 bugs +CONFIG_PPC601_SYNC_FIX + Some versions of the PPC601 (the first PowerPC chip) have bugs which + mean that extra synchronization instructions are required near certain + instructions, typically those that make major changes to the CPU state. + These extra instructions reduce performance slightly. If you say N + here, these extra instructions will not be included, resulting in a + kernel which will run faster but may not run at all on some systems + with the PPC601 chip. + + If in doubt, say Y here. Machine Type -CONFIG_PMAC +CONFIG_ALL_PPC Linux currently supports several different kinds of PowerPC-based machines: Apple Power Macintoshes and clones (such as the Motorola Starmax series), PReP (PowerPC Reference Platform) machines such as - the Motorola PowerStack, Amiga Power-Up systems (APUS), CHRP and the - embedded MBX boards from Motorola. Currently, a single kernel binary - only supports one type or the other. However, there is very early - work on support for CHRP, PReP and PowerMac's from a single binary. + the Motorola PowerStack, CHRP (Common Hardware Reference Platform), + the embedded MBX boards from Motorola and many others. Currently, + the default option is to build a kernel which works on the first + three. Support for other machines is currently incomplete. Power management support for PowerBooks CONFIG_PMAC_PBOOK @@ -15806,6 +16009,37 @@ an image of the device tree that the kernel copies from Open Firmware. If unsure, say Y here. +RTAS proc interface +CONFIG_PPC_RTAS + When you use this option, you will be able to use RTAS from + userspace. + + RTAS stands for RunTime Abstraction Services and should + provide a portable way to access and set system information. This is + commonly used on RS/6000 (pSeries) computers. + + You can access RTAS via the special proc filesystem entry rtas. + Don't confuse this rtas entry with the one in /proc/device-tree/rtas + which is readonly. + + If you don't know if you can use RTAS look into + /proc/device-tree/rtas. If there are some entries, it is very likely + that you will be able to use RTAS. + + You can do cool things with rtas. To print out information about + various sensors in the system, just do a + + $ cat /proc/rtas/sensors + + or if you power off your machine at night but want it running when + you enter your office at 7:45 am, do a + + # date -d 'tomorrow 7:30' +%s > /proc/rtas/poweron + + and shutdown. + + If unsure, say Y + MESH (Power Mac internal SCSI) support CONFIG_SCSI_MESH Many Power Macintoshes and clones have a MESH (Macintosh Enhanced @@ -16273,6 +16507,68 @@ from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +IBM's S/390 architecture +CONFIG_ARCH_S390 + Select this option, if you want to run the Kernel on one of IBM's + mainframes of the S/390 generation. You should have installed the + s390-compiler released by IBM (based on gcc-2.95.1) before. + +Merge some code into the kernel to make the image IPLable +CONFIG_IPLABLE + If you want to use the produced kernel to IPL directly from a + device, you have to merge a bootsector specific to the device + into the first bytes of the kernel. You will have to select the + IPL device on another question, that pops up, when you select + CONFIG_IPLABE. + +IPL from a /390 tape unit +CONFIG_IPL_TAPE + Select this option if you want to IPL the image from a Tape. + +IPL from a virtual card reader emulated by VM/ESA +CONFIG_IPL_RDR_VM + Select this option if you are running under VM/ESA and want + to IPL the image from the emulated card reader. + +IPL from a real card reader +CONFIG_IPL_RDR + Select this option if you want to IPL the image from a real + card reader. Maybe you still got one and want to try. We didn't + test. + +IBMs S/390 Harddisks (DASDs) +CONFIG_DASD + Enable this option if you want to access DASDs directly utilizing + S/390s channel subsystem commands. This is necessary for running + natively on a single image or an LPAR. + +Enable DASD fast write +CONFIG_DASD_FAST_IO + Enable fast I/O for DASDs. That means that the next I/O command + is already issued at interrupt time, if an I/O request is pending. + This option gives significant speedup of I/O, because we don't + schedule the bottom-halves as often as Intel. + +Support for IBM-style disk-labels (S/390) +CONFIG_S390_PARTITION + Enable this option to assure standard IBM labels on the DASDs. + You must enable it, if you are planning to access DASDs also + attached to another IBM mainframe operation system (OS/390, + VM/ESA, VSE/ESA). + +ECKD devices +CONFIG_DASD_ECKD + ECKD devices are the most commonly used devices. you should enable + this option unless you are very sure to have no ECKD device. + +CKD devices +CONFIG_DASD_CKD + CKD devices are currently unsupported. + +FBA devices +CONFIG_DASD_FBA + FBA devices are currently unsupported. + SAB3036 tuner support CONFIG_TUNER_3036 Say Y here to include support for Philips SAB3036 compatible tuners. @@ -16661,6 +16957,10 @@ This support is also available as a module called irda.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. + +IrDA protocol options +CONFIG_IRDA_OPTIONS + Say Y here if you want to configure any of the following IrDA options. IrDA Cache last LSAP CONFIG_IRDA_CACHE_LAST_LSAP diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/DocBook/kernel-api.tmpl linux.ac/Documentation/DocBook/kernel-api.tmpl --- linux-2.4.0/Documentation/DocBook/kernel-api.tmpl Sun Dec 31 02:16:13 2000 +++ linux.ac/Documentation/DocBook/kernel-api.tmpl Sun Dec 31 17:04:46 2000 @@ -34,6 +34,18 @@ + + + Driver Basic + Driver Entry and Exit points +!Iinclude/linux/init.h + + + Atomics +!Iinclude/asm-i386/atomic.h + + + Data Types Doubly Linked Lists diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/devices.txt linux.ac/Documentation/devices.txt --- linux-2.4.0/Documentation/devices.txt Sat Dec 30 19:26:10 2000 +++ linux.ac/Documentation/devices.txt Tue Jan 2 17:12:29 2001 @@ -660,6 +660,12 @@ 29 char Universal frame buffer 0 = /dev/fb0 First frame buffer + 1 = /dev/fb1 Second frame buffer + ... + 31 = /dev/fb31 32nd frame buffer + + Backward compatibility aliases {2.6} + 32 = /dev/fb1 Second frame buffer ... 224 = /dev/fb7 Eighth frame buffer @@ -765,7 +771,7 @@ 36 char Netlink support 0 = /dev/route Routing, device updates, kernel to user 1 = /dev/skip enSKIP security cache control - 3 = /dec/fwmonitor Firewall packet copies + 3 = /dev/fwmonitor Firewall packet copies 16 = /dev/tap0 First Ethertap device ... 31 = /dev/tap15 16th Ethertap device @@ -2436,7 +2442,7 @@ 224 char A2232 serial card 0 = /dev/ttyY0 First A2232 port - 1 = /dev/cuy0 Second A2232 port + 1 = /dev/ttyY1 Second A2232 port ... 225 char A2232 serial card (alternate devices) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/filesystems/ramfs.txt linux.ac/Documentation/filesystems/ramfs.txt --- linux-2.4.0/Documentation/filesystems/ramfs.txt Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/filesystems/ramfs.txt Wed Nov 22 01:14:10 2000 @@ -0,0 +1,47 @@ + ramfs - An automatically resizing memory based filesystem + + + Ramfs is a file system which keeps all files in RAM. It allows read + and write access. In contrast to RAM disks, which get allocated a + fixed amount of RAM, ramfs grows and shrinks to accommodate the + files it contains. + + You can mount the ramfs with: + mount -t ramfs none /mnt/wherever + + Then just create and use files. When the filesystem is unmounted, all + its contents are lost. + + NOTE! This filesystem is probably most useful not as a real + filesystem, but as an example of how virtual filesystems can be + written. + +Resource limits: + +By default a ramfs will be limited to using half of (physical) memory +for storing file contents, a bit over that when the metadata is +included. The resource usage limits of ramfs can be controlled with +the following mount options: + + maxsize=NNN + Sets the maximum allowed memory usage of the +filesystem to NNN kilobytes. This will be rounded down to a multiple +of the page size. The default is half of physical memory. NB. unlike +most of the other limits, setting this to zero does *not* mean no +limit, but will actually limit the size of the filesystem data to zero +pages. There might be a use for this in some perverse situation. + + maxfilesize=NNN + Sets the maximum size of a single file on the +filesystem to NNN kilobytes. This will be rounded down to a multiple +of the page size. If NNN=0 there is no limit. The default is no limit. + + maxdentries=NNN + Sets the maximum number of directory entries (hard +links) on the filesystem to NNN. If NNN=0 there is no limit. By +default this is set to maxsize/4. + + maxinodes=NNN + Sets the maximum number of inodes (i.e. distinct +files) on the filesystem to NNN. If NNN=0 there is no limit. The +default is no limit (but there can never be more inodes than dentries). diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/ioctl-number.txt linux.ac/Documentation/ioctl-number.txt --- linux-2.4.0/Documentation/ioctl-number.txt Mon Dec 11 21:42:08 2000 +++ linux.ac/Documentation/ioctl-number.txt Thu Jan 4 23:54:50 2001 @@ -82,6 +82,7 @@ 'B' C0-FF advanced bbus 'C' all linux/soundcard.h +'D' all asm-s390/dasd.h 'F' all linux/fb.h 'I' all linux/isdn.h 'J' 00-1F drivers/scsi/gdth_ioctl.h diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/magic-number.txt linux.ac/Documentation/magic-number.txt --- linux-2.4.0/Documentation/magic-number.txt Mon Feb 21 04:37:09 2000 +++ linux.ac/Documentation/magic-number.txt Mon Jan 1 20:57:14 2001 @@ -65,7 +65,6 @@ TTY_MAGIC 0x5401 tty_struct include/linux/tty.h TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h -SCC_MAGIC 0x8530 scc_channel include/linux/scc.h SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h CG_MAGIC 0x090255 ufs_cylinder_group include/linux/ufs_fs.h RPORT_MAGIC 0x525001 r_port drivers/char/rocket_int.h diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/s390/TAPE linux.ac/Documentation/s390/TAPE --- linux-2.4.0/Documentation/s390/TAPE Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/s390/TAPE Fri Jan 5 00:00:32 2001 @@ -0,0 +1,125 @@ +Channel attached Tape device driver + +-----------------------------WARNING----------------------------------------- +This driver is considered to be EXPERIMENTAL. Do NOT use it in +production environments. Feel free to test it and report problems back to us. +----------------------------------------------------------------------------- + +The LINUX for zSeries tape device driver manages channel attached tape drives +which are compatible to IBM 3480 or IBM 3490 magnetic tape subsystems. This +includes various models of these devices (for example the 3490E). + + +Tape driver features + +The device driver supports a maximum of 128 tape devices. +No official LINUX device major number is assigned to the zSeries tape device +driver. It allocates major numbers dynamically and reports them on system +startup. +Typically it will get major number 254 for both the character device front-end +and the block device front-end. + +The tape device driver needs no kernel parameters. All supported devices +present are detected on driver initialization at system startup or module load. +The devices detected are ordered by their subchannel numbers. The device with +the lowest subchannel number becomes device 0, the next one will be device 1 +and so on. + + +Tape character device front-end + +The usual way to read or write to the tape device is through the character +device front-end. The zSeries tape device driver provides two character devices +for each physical device -- the first of these will rewind automatically when +it is closed, the second will not rewind automatically. + +The character device nodes are named /dev/rtibm0 (rewinding) and /dev/ntibm0 +(non-rewinding) for the first device, /dev/rtibm1 and /dev/ntibm1 for the +second, and so on. + +The character device front-end can be used as any other LINUX tape device. You +can write to it and read from it using LINUX facilities such as GNU tar. The +tool mt can be used to perform control operations, such as rewinding the tape +or skipping a file. + +Most LINUX tape software should work with either tape character device. + + +Tape block device front-end + +The tape device may also be accessed as a block device in read-only mode. +This could be used for software installation in the same way as it is used with +other operation systems on the zSeries platform (and most LINUX +distributions are shipped on compact disk using ISO9660 filesystems). + +One block device node is provided for each physical device. These are named +/dev/btibm0 for the first device, /dev/btibm1 for the second and so on. +You should only use the ISO9660 filesystem on LINUX for zSeries tapes because +the physical tape devices cannot perform fast seeks and the ISO9660 system is +optimized for this situation. + + +Tape block device example + +In this example a tape with an ISO9660 filesystem is created using the first +tape device. ISO9660 filesystem support must be built into your system kernel +for this. +The mt command is used to issue tape commands and the mkisofs command to +create an ISO9660 filesystem: + +- create a LINUX directory (somedir) with the contents of the filesystem + mkdir somedir + cp contents somedir + +- insert a tape + +- ensure the tape is at the beginning + mt -f /dev/ntibm0 rewind + +- set the blocksize of the character driver. The blocksizes 512, 1024 + and 2048 bytes are supported by ISO9660. 1024 is the default, u + which will be used here. + mt -f /dev/ntibm0 setblk 1024 + +- write the filesystem to the character device driver + mkisofs -o /dev/ntibm0 somedir + +- rewind the tape again + mt -f /dev/ntibm0 rewind + +- Now you can mount your new filesystem as a block device: + mount -t iso9660 -o ro,block=1024 /dev/btibm0 /mnt + +TODO List + +- The backend code has to be enhanced to support error-recovery actions. + +- The seeking algorithm of the block device has to be improved to speed + things up + +BUGS + +There are lots of weaknesses still in the code. This is why it is EXPERIMENTAL. +If an error occurs which cannot be handled by the code you will get a +sense-data dump.In that case please do the following: + +1. set the tape driver debug level to maximum: + echo 6 >/proc/s390dbf/tape/level + +2. re-perform the actions which produced the bug. (Hopefully the bug will + reappear.) + +3. get a snapshot from the debug-feature: + cat /proc/s390dbf/tape/hex_ascii >somefile + +4. Now put the snapshot together with a detailed description of the situation + that led to the bug: + - Which tool did you use? + - Which hardware do you have? + - Was your tape unit online? + - Is it a shared tape unit? + +5. Send an email with your bug report to: + mailto:Linux390@de.ibm.com + + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/s390/chandev.8 linux.ac/Documentation/s390/chandev.8 --- linux-2.4.0/Documentation/s390/chandev.8 Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/s390/chandev.8 Fri Jan 5 00:00:32 2001 @@ -0,0 +1,306 @@ +.TH chandev 8 +.SH NAME +channel device layer +.Dd December 6, 2000 +.Os Linux for Zseries + +.SH SYNOPSIS +The channel device layer is a layer to provide a consistent interface for +configuration & default machine check (devices appearing & disappearing ) +handling Linux for zSeries channel devices. + +These include among others + +.Bl -item +.It +lcs ( the most common ethernet/token ring/fddi standard on zSeries ) +.It +ctc/escon hi speed like serial link standard on zSeries. +.It +claw used to talk to cisco routers. +.It +qeth gigabit ethernet. +.El + +These devices use two channels one read & one write for configuration & +or communication. +The motivation behind producing this layer was that there is a lot of +duplicate code among the drivers for configuration so the lcs & ctc drivers +tended to fight over 3088/08's & 3088/1F's which could be either 2216/3172 +lcs compatible devices or escons/ctc's & to resolve this fight +both device drivers had to be reconfigured rather than doing the +configuration in a single place. + +.SH DESCRIPTION +The current setup can be read from /proc/chandev +arguments can be entered by... +.Bl -enum +.It +Piping to /proc/chandev. +.It +Entering them into /etc/chandev.conf comments are prefixed #. +.It +Or from the boot command line using the 'chandev=' keyword +.El +Multiple options can be passed separated by semicolons but no spaces are allowed between parameters. The script /bin/chandev will be called automatically on startup or a machine check of a device as follows. +/bin/chandev . + +e.g. if tr0 & ctc0 were starting up & eth0 & eth1 didn't recover from a gone machine check at the same instant the parameters would be. + + +/bin/chandev start tr0 ctc0 machine_check eth0 gone gone eth1 gone gone + + +This can be used for example to call /etc/rc.d/init.d/network start when a device appears & make the ipldelay kernel boot parameter obselete on native machines or recover from bad machine checks where the default machine check handling isn't adequete. The machine checks that can be presented as parameters are good not_operational no_path revalidate device_gone. + +valid chandev arguments are <> indicate optional parameters, | indicate a choice. + +.B glossary +.Bl -item +.It +devno: is a 16 bit unsigned number used to uniquely identify a subchannel to a device. +.It +force list: is a term specific to channel device layer describing a range of devno's to be forced to configure in a particular manner as opposed to autodetect +.El + +.B commonly used options + +.Bl -item +.It + +.Bl -item + +.It +.B (ctc|escon|lcs|osad|qeth|claw), +read_devno, write_devno, , , +.It +e.g. ctc0,0x7c00,0x7c01,0,0,0 +.It +Tells the channel layer to force ctc0 if detected to use cuu's 7c00 & 7c01 port,port_no is the relative adapter no on lcs, on ctc/escon this field is the ctc/escon protocol number ( normally 0 ), don't do checksumming on received ip packets & as ctc doesn't have hardware stats so it ignores this parameter. +.El +.It + +.Bl -item +.It +.B add_parms +,chan_type, +.It +chan_type bitfield +.It +ctc=0x1, escon=0x2, lcs=0x4, osad=0x8, qeth=0x10, claw=0x20. +.It +This is for device driver specific options passed as a string to the driver +not dealt with by the channel device layer it can't contain spaces. +.El +.It + +.Bl -item +.It +.B del_parms +<,chan_type,exact_match> +.It +This deletes some or all device driver specific options not specifying chan_type causes it to delete all the strings. exact_match=1 specifies only to remove driver parms where chan_type is exactly equal exact_match=0 specifies to remove parms where any bit matches chan_type. +.El +.It + +.Bl -item +.It +.B noauto +,- +.It +Don't probe a range of device numbers for channel devices. +.El +.It + +.Bl -item +.It +.B use_devno_names +.It +Tells the channel layer to assign device names based on the read channel cuu number. +.It +e.g. a token ring read channel 0x7c00 would have an interface called tr0x7c00 this avoids name collisions on devices. +.El +.El + + +.B power user options + + +.Bl -item + +.It +.Bl -item +.It +.B del_noauto +, +.It + Delete a range or all noauto ranges when devno is within a range. +.El + +.It +.Bl -item +.It +.B del_force +,read_devno +.It +Delete a forced channel device from force list. +.El + +.It +.Bl -item +.It +.B dont_use_devno_names +.It +Opposite to use_devno_names described above. +.El + + +.It +.Bl -item +.It +.B add_model +,chan_type, cu_type, cu_model, dev_type, dev_model, max_port_no, automatic_machine_check_handling + +.It +Tells the channel layer to probe for the device described, -1 for any of the parameters other than chan_type & automatic_machine_check_handling is a wildcard. +Set max_port_no to 0 for non lcs devices. +.It +auto machine check recovery bitfield +.It +not_operational=0x1, no_path=0x2, revalidate=0x4, gone=0x8 +.It +chan_type bitfield +.It +ctc=0x1, escon=0x2, lcs=0x4, osad=0x8, qeth=0x10, claw=0x20 + +.It +.Bl -item +.It +.B del_model +,cu_type,cu_model,dev_type,dev_model +.It +-1 for any parameter is a wildcard, +.El +.It +.B del_all_models +.It +.Bl -item +.It +.B auto_msck +<,lo_devno>,,auto_msck_recovery +.It +This is used to specify the kind of machine check recovery that occurs over a device range. +.El +.It +.Bl -item +.It +.B del_auto_msck +<,devno> +.It +Delete a range or all machine check recovery ranges when devno is within a range. +.El +.It +.Bl -item +.It +.B reset_clean +.It +Resets all model info, forced devices & noauto lists to null. +.El +.It +.Bl -item +.It +.B reset_conf +.It +Resets all model info, forced devices & noauto lists back to default settings. +.El +.It +.Bl -item +.It +.B reset_conf_clean +.It +Resets all model info, forced devices & noauto lists to empty. +.El +.It +.Bl -item +.It +.B shutdown + +.It +Shuts down a particular device by device name or read devno, +deregisters it & releases its interrupts +or shuts down all devices if no parameter is used. +.El +.It +.Bl -item +.It +.B reprobe +.It +Calls probe method for channels whose interrupts are not owned. +.El +.It +.Bl -item +.It +.B read_conf +.It +Read instructions from /etc/chandev.conf. +.El +.It +.Bl -item +.It +.B dont_read_conf +.It +Don't automatically read /etc/chandev.conf on boot. +.El +.It +e.g the following sequence of commands should be roughly equivalent +to rebooting for channel devices. +.Bl -item +.It +shutdown +.It +reset_conf +.It +read_conf +.It +reprobe +.El +.El + +.SH SEE ALSO +.Bl -item +.It +If you wish to write a driver channel device layer compatible +.It +/linux/include/asm-s390/chandev.h for the apis which are commented. +.It +/linux/drivers/s390/misc/chandev.c for the code. +.El + +.SH FILES +.Bl -item +.It +.B /proc/chandev +.It +cat /proc/chandev to see current options chosen. +.Iy +echo >proc/chandev to enter a new command +.It +.B /etc/chandev.conf +.It +A file which can be used to configure the channel +device layer. +.It +kernel parameters with the +.B 'chandev=' +keyword. +.It +.B /bin/chandev +.It +A user script/executable which is run when devices come online "appear" +or go offline "disappear". +.El + + +.SH AUTHORS +DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Documentation/usb/usb-serial.txt linux.ac/Documentation/usb/usb-serial.txt --- linux-2.4.0/Documentation/usb/usb-serial.txt Fri Dec 8 00:13:38 2000 +++ linux.ac/Documentation/usb/usb-serial.txt Thu Dec 21 21:23:32 2000 @@ -223,7 +223,7 @@ To enable the generic driver to recognize your device, build the driver as a module and load it by the following invocation: - insmod usb-serial vendor=0x#### product=0x#### + insmod usbserial vendor=0x#### product=0x#### where the #### is replaced with the hex representation of your device's vendor id and product id. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/MAINTAINERS linux.ac/MAINTAINERS --- linux-2.4.0/MAINTAINERS Sun Dec 31 17:31:15 2000 +++ linux.ac/MAINTAINERS Thu Jan 4 23:54:50 2001 @@ -484,6 +484,12 @@ W: http://www.icp-vortex.com/ S: Supported +GENERIC HDLC DRIVER, N2 AND C101 DRIVERS +P: Krzysztof Halasa +M: khc@pm.waw.pl +W: http://hq.pm.waw.pl/hdlc/ +S: Maintained + HAYES ESP SERIAL DRIVER P: Andrew J. Robinson M: arobinso@nyx.net @@ -1041,6 +1047,14 @@ L: rtl@rtlinux.org W: www.rtlinux.org S: Maintained + +S390 +P: Martin Schwidefsky +M: schwidefsky@de.ibm.com +M: linux390@de.ibm.com +L: linux-390@vm.marist.edu +W: http://oss.software.ibm.com/developerworks/opensource/linux390 +S: Supported SA1100 SUPPORT P: Nicolas Pitre diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/Makefile linux.ac/Makefile --- linux-2.4.0/Makefile Thu Jan 4 21:48:13 2001 +++ linux.ac/Makefile Fri Jan 5 15:01:19 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -ac2 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -145,6 +145,7 @@ DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o +DRIVERS-$(CONFIG_FUSION_BOOT) += drivers/message/fusion/fusion.o DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),) @@ -171,7 +172,7 @@ DRIVERS-$(CONFIG_TC) += drivers/tc/tc.a DRIVERS-$(CONFIG_USB) += drivers/usb/usbdrv.o DRIVERS-$(CONFIG_INPUT) += drivers/input/inputdrv.o -DRIVERS-$(CONFIG_I2O) += drivers/i2o/i2o.o +DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/alpha/config.in linux.ac/arch/alpha/config.in --- linux-2.4.0/arch/alpha/config.in Fri Dec 29 22:07:19 2000 +++ linux.ac/arch/alpha/config.in Sun Dec 31 22:30:03 2000 @@ -278,6 +278,8 @@ fi endmenu +source drivers/message/fusion/Config.in + if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment comment 'Network device support' diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/Makefile linux.ac/arch/arm/Makefile --- linux-2.4.0/arch/arm/Makefile Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/Makefile Sun Dec 31 14:57:34 2000 @@ -12,25 +12,18 @@ # # Copyright (C) 1995-2000 by Russell King -OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S -CPP := $(CC) -E -LINKFLAGS := -p -X -T arch/arm/vmlinux.lds -ARCHCC := $(word 1,$(CC)) - -AFLAGS += -mno-fpu -CFLAGS_PIPE := -pipe -CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) -msoft-float +LINKFLAGS :=-p -X -T arch/arm/vmlinux.lds +GZFLAGS :=-9 +CFLAGS +=-fno-common -pipe ifdef CONFIG_FRAME_POINTER -CFLAGS := $(CFLAGS:-fomit-frame-pointer=) +CFLAGS :=$(CFLAGS:-fomit-frame-pointer=) endif ifdef CONFIG_DEBUG_INFO -CFLAGS += -g +CFLAGS +=-g endif -GZFLAGS = -9 - # Ensure this is ld "2.9.4" or later NEW_LINKER := $(shell $(LD) --gc-sections --version >/dev/null 2>&1; echo $$?) @@ -40,61 +33,42 @@ @false endif -# GCC 2.7 uses different options to later compilers; sort out which we have -NEW_GCC := $(shell $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; echo $$?) - -# -# select flags depending on the compiler +# Select CPU dependent flags. Note that order of declaration is important; +# the options further down the list override previous items. # -ifneq ($(NEW_GCC),0) -CFLAGS += -mshort-load-bytes -CFLAGS_PROC_CPU_26 := -mcpu=arm3 -mapcs-26 -Os -CFLAGS_PROC_CPU_32v3 := -march=armv3 -CFLAGS_PROC_CPU_32v4 := -march=armv4 -else -CFLAGS += -DNO_TEXT_SECTIONS -CFLAGS_PROC_CPU_26 := -m3 -CFLAGS_PROC_CPU_32v3 := -m6 -CFLAGS_PROC_CPU_32v4 := -m6 -endif +apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 -Os +apcs-$(CONFIG_CPU_32) :=-mapcs-32 + +arch-$(CONFIG_CPU_32v3) :=-march=armv3 +arch-$(CONFIG_CPU_32v4) :=-march=armv4 +arch-$(CONFIG_CPU_32v5) :=-march=armv5 + +proc-$(CONFIG_CPU_32v3) :=-marmv3m +proc-$(CONFIG_CPU_32v4) :=-marmv4 +proc-$(CONFIG_CPU_32v5) :=-marmv5 + +tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610 +tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710 +tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi +tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi +tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 +tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 + +CFLAGS += $(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float +AFLAGS += $(apcs-y) $(proc-y) -mno-fpu + +LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -# -# Select CPU dependent flags -# ifeq ($(CONFIG_CPU_26),y) - PROCESSOR = armo - TEXTADDR = 0x02080000 - CFLAGS += $(CFLAGS_PROC_CPU_26) - AFLAGS += -mapcs-26 +PROCESSOR = armo +TEXTADDR = 0x02080000 endif ifeq ($(CONFIG_CPU_32),y) - PROCESSOR = armv - TEXTADDR = 0xC0008000 - ifeq ($(CONFIG_CPU_32v4),y) - CFLAGS += $(CFLAGS_PROC_CPU_32v4) - AFLAGS += -mapcs-32 -marmv4 - else - CFLAGS += $(CFLAGS_PROC_CPU_32v3) - AFLAGS += -mapcs-32 -marmv3m - endif - - opt-$(CONFIG_CPU_ARM6) := -mtune=arm6 - opt-$(CONFIG_CPU_ARM7) := -mtune=arm7 - opt-$(CONFIG_CPU_ARM720) := -mtune=arm7tdmi - opt-$(CONFIG_CPU_ARM920) := -mtune=arm9tdmi - opt-$(CONFIG_CPU_SA110) := -mtune=strongarm110 - opt-$(CONFIG_CPU_SA1100) := -mtune=strongarm110 - - ifneq ($(NEW_GCC),0) - CFLAGS += $(opt-y) - endif +PROCESSOR = armv +TEXTADDR = 0xC0008000 endif -LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) - -export LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS - ifeq ($(CONFIG_ARCH_ARCA5K),y) MACHINE = arc endif @@ -132,6 +106,10 @@ endif ifeq ($(CONFIG_ARCH_SA1100),y) +ifeq ($(CONFIG_SA1111),y) +# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory +TEXTADDR = 0xc0208000 +endif MACHINE = sa1100 endif @@ -143,6 +121,13 @@ MACHINE = integrator endif +ifeq ($(CONFIG_ARCH_CLPS711X),y) +TEXTADDR = 0xc0018000 +MACHINE = clps711x +endif + +export LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS + # Only set INCDIR if its not already defined above # Grr, ?= doesn't work as all the other assignment operators do. Make bug? ifeq ($(origin INCDIR), undefined) @@ -158,8 +143,7 @@ HEAD := arch/arm/kernel/head-$(PROCESSOR).o \ arch/arm/kernel/init_task.o -SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib \ - arch/arm/nwfpe +SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) LIBS := arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(LIBGCC) @@ -167,14 +151,6 @@ LIBS := arch/arm/nwfpe/math-emu.o $(LIBS) endif -ifeq ($(CONFIG_ARCH_ACORN),y) -SUBDIRS += drivers/acorn -DRIVERS += drivers/acorn/block/acorn-block.a -DRIVERS += drivers/acorn/char/acorn-char.o -DRIVERS += drivers/acorn/net/acorn-net.o -DRIVERS += drivers/acorn/scsi/acorn-scsi.a -endif - ifeq ($(CONFIG_ARCH_CLPS7500),y) SUBDIRS += drivers/acorn/char DRIVERS += drivers/acorn/char/acorn-char.o @@ -230,6 +206,7 @@ Img:; @$(MAKEBOOT) Image i:; @$(MAKEBOOT) install zi:; @$(MAKEBOOT) zinstall +bp:; @$(MAKEBOOT) bootpImage # # Configuration targets. Use these to select a @@ -237,9 +214,10 @@ CFGS= a5k_config ebsa110_config \ footbridge_config rpc_config \ brutus_config victor_config \ - empeg_config thinclient_config \ + empeg_config graphicsclient_config \ assabet_config lart_config \ - cerf_config lusl7200_config + cerf_config lusl7200_config \ + sherman_config pangolin_config $(CFGS): @( \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/Makefile linux.ac/arch/arm/boot/Makefile --- linux-2.4.0/arch/arm/boot/Makefile Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/boot/Makefile Sun Dec 31 14:57:34 2000 @@ -83,15 +83,18 @@ ZRELADDR = 0xc0008000 ifeq ($(CONFIG_SA1100_VICTOR),y) ZTEXTADDR = 0x00002000 - ZBSSADDR = 0xc0100000 + ZBSSADDR = 0xc0200000 endif ifeq ($(CONFIG_SA1100_SHERMAN),y) ZTEXTADDR = 0x00050000 - ZBSSADDR = 0xc0100000 + ZBSSADDR = 0xc0200000 endif ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) ZTEXTADDR = 0xC0200000 endif +ifeq ($(CONFIG_SA1111),y) + ZRELADDR = 0xc0208000 +endif endif # @@ -105,15 +108,15 @@ export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS Image: $(CONFIGURE) $(SYSTEM) - $(OBJCOPY) $(SYSTEM) $@ + $(OBJCOPY) -O binary -R .note -R .comment -S $(SYSTEM) $@ bzImage: zImage zImage: $(CONFIGURE) compressed/vmlinux - $(OBJCOPY) compressed/vmlinux $@ + $(OBJCOPY) -O binary -R .note -R .comment -S compressed/vmlinux $@ bootpImage: bootp/bootp - $(OBJCOPY) bootp/bootp $@ + $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ compressed/vmlinux: $(TOPDIR)/vmlinux dep @$(MAKE) -C compressed vmlinux diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/bootp/Makefile linux.ac/arch/arm/boot/bootp/Makefile --- linux-2.4.0/arch/arm/boot/bootp/Makefile Sun Sep 3 19:19:11 2000 +++ linux.ac/arch/arm/boot/bootp/Makefile Sun Dec 31 14:55:50 2000 @@ -7,7 +7,8 @@ ZLDFLAGS =-p -X -T bootp.lds \ --defsym initrd_addr=$(INITRD_PHYS) \ --defsym initrd_virt=$(INITRD_VIRT) \ - --defsym params=$(PARAMS_PHYS) + --defsym params=$(PARAMS_PHYS) \ + --defsym kernel_addr=$(ZTEXTADDR) all: bootp diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/bootp/init.S linux.ac/arch/arm/boot/bootp/init.S --- linux-2.4.0/arch/arm/boot/bootp/init.S Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/boot/bootp/init.S Sun Dec 31 14:55:50 2000 @@ -12,33 +12,59 @@ */ .section .start,#alloc,#execinstr .type _entry, #function -_entry: -kernel_addr: adr r10, initdata - ldmia r10, {r11, r12} +_entry: adr r10, initdata + ldr r11, initdata sub r11, r10, r11 @ work out exec offset - add r12, r12, r11 @ correct "splitify" - mov pc, r12 @ jump to splitify + b splitify .size _entry,. - _entry .type initdata, #object initdata: .word initdata @ compiled address of this - .word splitify .size initdata,. - initdata .text splitify: adr r13, data - ldmia r13!, {r4-r6} @ move the kernel + ldmia r13!, {r4-r6} @ move the initrd add r4, r4, r11 @ correction - mov r12, r5 bl move - ldmia r13!, {r4-r6} @ then the initrd + ldmia r13!, {r4-r6} @ then the kernel + mov r12, r5 add r4, r4, r11 @ correction bl move - ldmib r13, {r5,r6,r7} @ get size and addr of initrd - add r7, r7, #16*4 @ offset of initrd_start in param_struct - stmia r7, {r5,r6} @ save in param_struct +/* + * Setup the initrd parameters to pass to the kernel. This can either be + * passed in via a param_struct or a tag list. We spot the param_struct + * method by looking at the first word; this should either indicate a page + * size of 4K, 16K or 32K. + */ + ldmia r13, {r5-r8} @ get size and addr of initrd + @ r5 = ATAG_INITRD + @ r6 = initrd start + @ r7 = initrd end + @ r8 = param_struct address + ldr r9, [r8, #0] @ no param struct? + teq r9, #0x1000 @ 4K? + teqne r9, #0x4000 @ 16K? + teqne r9, #0x8000 @ 32K? + beq no_taglist + +/* + * find the end of the tag list, and then add an INITRD tag on the end. + */ +taglist: ldr r9, [r8, #0] @ tag length + teq r9, #0 @ last tag? + addne r8, r8, r9 + bne taglist + + mov r4, #16 @ length of initrd tag + mov r9, #0 @ end of tag list terminator + stmia r8, {r4, r5, r6, r7, r9} + mov pc, r12 @ call kernel + +no_taglist: add r8, r8, #16*4 + stmia r8, {r6,r7} @ save in param_struct mov pc, r12 @ call kernel move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time @@ -49,17 +75,18 @@ bcs move mov pc, lr -data: .word kernel_start - .word kernel_addr - .word kernel_len - - .word initrd_start +data: .word initrd_start .word initrd_addr .word initrd_len - .word initrd_virt - .word initrd_len - .word params + .word kernel_start + .word kernel_addr + .word kernel_len + + .word 0x54410005 @ r5 = ATAG_INITRD + .word initrd_virt @ r6 + .word initrd_len @ r7 + .word params @ r8 .type kernel_start,#object .type initrd_start,#object diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/Makefile linux.ac/arch/arm/boot/compressed/Makefile --- linux-2.4.0/arch/arm/boot/compressed/Makefile Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/boot/compressed/Makefile Sun Dec 31 14:57:34 2000 @@ -66,7 +66,7 @@ $(CC) $(AFLAGS) -traditional -c $(HEAD:.o=.S) piggy.o: $(SYSTEM) - $(OBJCOPY) $(SYSTEM) piggy + $(OBJCOPY) -O binary -R .note -R .comment -S $(SYSTEM) piggy gzip $(GZFLAGS) < piggy > piggy.gz $(LD) -r -o $@ -b binary piggy.gz rm -f piggy piggy.gz diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/head-ftvpci.S linux.ac/arch/arm/boot/compressed/head-ftvpci.S --- linux-2.4.0/arch/arm/boot/compressed/head-ftvpci.S Sun Sep 3 19:19:11 2000 +++ linux.ac/arch/arm/boot/compressed/head-ftvpci.S Sun Dec 31 14:56:45 2000 @@ -6,6 +6,13 @@ * Special startup code for FTV PCI board. */ +/* + * 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. + */ + .section ".start", #alloc, #execinstr ftv_start: mcr p15, 0, r0, c7, c5, 0 @ flush I cache diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/head-l7200.S linux.ac/arch/arm/boot/compressed/head-l7200.S --- linux-2.4.0/arch/arm/boot/compressed/head-l7200.S Sun Aug 13 17:54:15 2000 +++ linux.ac/arch/arm/boot/compressed/head-l7200.S Sun Dec 31 14:56:45 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 2000 Steve Hill * - * Some code borrowed from Nicola Pitre's 'head-sa1100.S' file. This + * Some code borrowed from Nicolas Pitre's 'head-sa1100.S' file. This * is merged with head.S by the linker. */ @@ -16,15 +16,14 @@ .section ".start", #alloc, #execinstr __L7200_start: - mov r0, #0x00100000 @ FLASH address of initrd mov r2, #0xf1000000 @ RAM address of initrd - add r1, r2, #0x00700000 @ Size of initrd + add r3, r2, #0x00700000 @ Size of initrd 1: - ldmia r0!, {r3, r4, r5, r6} - stmia r2!, {r3, r4, r5, r6} - cmp r2, r1 + ldmia r0!, {r4, r5, r6, r7} + stmia r2!, {r4, r5, r6, r7} + cmp r2, r3 ble 1b - + mov r8, #0 @ Zero it out mov r7, #19 @ Set architecture ID diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/head-sa1100.S linux.ac/arch/arm/boot/compressed/head-sa1100.S --- linux-2.4.0/arch/arm/boot/compressed/head-sa1100.S Sun Aug 13 17:54:15 2000 +++ linux.ac/arch/arm/boot/compressed/head-sa1100.S Sun Dec 31 14:56:45 2000 @@ -11,10 +11,6 @@ #include #include -#ifndef CONFIG_ARCH_SA1100 -#error What am I doing here... -#endif - .section ".start", #alloc, #execinstr __SA1100_start: @@ -54,6 +50,8 @@ bic r0, r0, #0x0d @ clear WB, DC, MMU bic r0, r0, #0x1000 @ clear Icache mcr p15, 0, r0, c1, c0, 0 + +#ifdef CONFIG_ANGELBOOT /* * Pause for a short time so that we give enough time * for the host to start a terminal up. @@ -61,3 +59,5 @@ mov r0, #0x00200000 1: subs r0, r0, #1 bne 1b +#endif + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/head-shark.S linux.ac/arch/arm/boot/compressed/head-shark.S --- linux-2.4.0/arch/arm/boot/compressed/head-shark.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/boot/compressed/head-shark.S Sun Dec 31 14:56:45 2000 @@ -0,0 +1,121 @@ +/* The head-file for the Shark + * by Alexander.Schulz@stud.uni-karlsruhe.de + * + * Does the following: + * - get the memory layout from firmware. This can only be done as long as the mmu + * is still on. + * - switch the mmu off, so we have physical addresses + * - copy the kernel to 0x08508000. This is done to have a fixed address where the + * C-parts (misc.c) are executed. This address must be known at compile-time, + * but the load-address of the kernel depends on how much memory is installed. + * - Jump to this location. + * - Set r8 with 0, r7 with the architecture ID for head.S + */ + +#include + +#include + + .section ".start", #alloc, #execinstr + + b __beginning + +__serial_addr: .long 0xf7eff3f8 + .long 0 @ space +__ofw_data: .long 0 @ the number of memory blocks + .space 128 @ (startaddr,size) ... + .space 128 @ bootargs + .align + +__beginning: mov r4, r0 @ save the entry to the firmware + + mov r0, #0xC0 @ disable irq and fiq + mov r1, r0 + mrs r3, cpsr_all + bic r2, r3, r0 + eor r2, r2, r1 + msr cpsr_all, r2 + + ldr r0, __serial_addr @ disable serial interrupt + mov r1, #0 @ hangs the machine, I don t know why. + strb r1, [r0, #0x01] + + mov r0, r4 @ get the Memory layout from firmware + adr r1, __ofw_data + add r2, r1, #4 + mov lr, pc + b SYMBOL_NAME(ofw_init) + mov r1, #0 + + adr r2, __mmu_off @ calculate physical address + sub r2, r2, #0xf0000000 @ openprom maps us at f000 virt, 0e50 phys + adr r0, __ofw_data + ldr r0, [r0, #4] + add r2, r2, r0 + add r2, r2, #0x00500000 + + mrc p15, 0, r3, c1, c0 + bic r3, r3, #0xC @ Write Buffer and DCache + bic r3, r3, #0x1000 @ ICache + mcr p15, 0, r3, c1, c0 @ disabled + + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 + + bic r3, r3, #0x1 @ MMU + mcr p15, 0, r3, c1, c0 @ disabled + + mov pc, r2 + +__copy_target: .long 0x08508000 +__copy_end: .long 0x08608000 + + .word _start + .word __bss_start + + .align +__temp_stack: .space 128 + +__mmu_off: + adr r0, __ofw_data + ldr r0, [r0, #4] + orr r0, r0, #0x00600000 + + ldr r1, __copy_end + ldr r3, __copy_target + +/* r0 = 0x0e600000 (current end of kernelcode) + * r3 = 0x08508000 (where it should begin) + * r1 = 0x08608000 (end of copying area, 1MB) + * The kernel is compressed, so 1 MB should be enough. + * copy the kernel to the beginning of physical memory + * We start from the highest address, so we can copy + * from 0x08500000 to 0x08508000 if we have only 8MB + */ + + +__Copy: ldr r2, [r0], #-4 + str r2, [r1], #-4 + teq r1, r3 + bne __Copy + /* and jump to it */ + adr r2, __go_on + adr r0, __ofw_data + ldr r0, [r0, #4] + sub r2, r2, r0 + sub r2, r2, #0x00500000 + ldr r0, __copy_target + add r2, r2, r0 + mov pc, r2 + +__go_on: + adr sp, __temp_stack + add sp, sp, #128 + adr r0, __ofw_data + mov lr, pc + b SYMBOL_NAME(create_params) + + mov r8, #0 + mov r7, #15 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/head.S linux.ac/arch/arm/boot/compressed/head.S --- linux-2.4.0/arch/arm/boot/compressed/head.S Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/boot/compressed/head.S Sun Dec 31 14:56:45 2000 @@ -112,8 +112,7 @@ */ .text -1: mrc p15, 0, r6, c0, c0 @ get processor ID - adr r2, LC0 +1: adr r2, LC0 ldmia r2, {r2, r3, r4, r5, sp} mov r0, #0 @@ -124,14 +123,15 @@ cmp r2, r3 blt 1b + mrc p15, 0, r6, c0, c0 @ get processor ID bl cache_on mov r1, sp @ malloc space above stack add r2, sp, #0x10000 @ 64k max teq r4, r5 @ will we overwrite ourselves? - moveq r5, r2 - movne r5, r4 + moveq r5, r2 @ decompress after image + movne r5, r4 @ decompress to final location mov r0, r5 mov r3, r7 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/ofw-shark.c linux.ac/arch/arm/boot/compressed/ofw-shark.c --- linux-2.4.0/arch/arm/boot/compressed/ofw-shark.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/boot/compressed/ofw-shark.c Sun Dec 31 14:56:45 2000 @@ -0,0 +1,216 @@ +/* + * linux/arch/arm/boot/compressed/ofw-shark.c + * + * by Alexander.Schulz@stud.uni-karlsruhe.de + * + * This file is used to get some basic information + * about the memory layout of the shark we are running + * on. Memory is usually divided in blocks a 8 MB. + * And bootargs are copied from OpenFirmware. + */ + + +#include +#include +#include + + +asmlinkage void +create_params (unsigned long *buffer) +{ + /* Is there a better address? Also change in kernel/arch.c */ + struct param_struct *params = (struct param_struct *) 0x08003000; + int j,i,m,k,nr_banks,size; + + for (j=0;j<256;j++) params->u1.unused[j]=0; + + size=0; + nr_banks=(unsigned int) buffer[0]; + if (nr_banks > NR_BANKS) nr_banks = NR_BANKS; + for (j=0;ju1.s.pages_in_bank[j]=buffer[2*k+1]|(buffer[2*k+2]/PAGE_SIZE); + size += buffer[2*k+2]; + + buffer[2*k+1]=0xffffffff; /* mark as copied */ + } + + params->u1.s.page_size = PAGE_SIZE; + params->u1.s.nr_pages = size/PAGE_SIZE; + params->u1.s.flags = FLAG_READONLY; + + /* Copy over the bootargs */ + for (j=0;j<128/4;j++) { + ((unsigned long *) params->commandline)[j]=buffer[33+j]; + } +} + + +typedef int (*ofw_handle_t)(void *); + +/* Everything below is called with a wrong MMU setting. + * This means: no string constants, no initialization of + * arrays, no global variables! This is ugly but I didn't + * want to write this in assembler :-) + */ + +int +of_decode_int(const unsigned char *p) +{ + unsigned int i = *p++ << 8; + i = (i + *p++) << 8; + i = (i + *p++) << 8; + return (i + *p); +} + +int +OF_finddevice(ofw_handle_t openfirmware, char *name) +{ + unsigned int args[8]; + char service[12]; + + service[0]='f'; + service[1]='i'; + service[2]='n'; + service[3]='d'; + service[4]='d'; + service[5]='e'; + service[6]='v'; + service[7]='i'; + service[8]='c'; + service[9]='e'; + service[10]='\0'; + + args[0]=(unsigned int)service; + args[1]=1; + args[2]=1; + args[3]=(unsigned int)name; + + if (openfirmware(args) == -1) + return -1; + return args[4]; +} + +int +OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop) +{ + unsigned int args[8]; + char service[12]; + + service[0]='g'; + service[1]='e'; + service[2]='t'; + service[3]='p'; + service[4]='r'; + service[5]='o'; + service[6]='p'; + service[7]='l'; + service[8]='e'; + service[9]='n'; + service[10]='\0'; + + args[0] = (unsigned int)service; + args[1] = 2; + args[2] = 1; + args[3] = (unsigned int)handle; + args[4] = (unsigned int)prop; + + if (openfirmware(args) == -1) + return -1; + return args[5]; +} + +int +OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen) +{ + unsigned int args[8]; + char service[8]; + + service[0]='g'; + service[1]='e'; + service[2]='t'; + service[3]='p'; + service[4]='r'; + service[5]='o'; + service[6]='p'; + service[7]='\0'; + + args[0] = (unsigned int)service; + args[1] = 4; + args[2] = 1; + args[3] = (unsigned int)handle; + args[4] = (unsigned int)prop; + args[5] = (unsigned int)buf; + args[6] = buflen; + + if (openfirmware(args) == -1) + return -1; + return args[7]; +} + +asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) +{ + int phandle,i,mem_len,buffer[32]; + char temp[12]; + + temp[0]='/'; + temp[1]='m'; + temp[2]='e'; + temp[3]='m'; + temp[4]='o'; + temp[5]='r'; + temp[6]='y'; + temp[7]='\0'; + + phandle=OF_finddevice(o,temp); + + temp[0]='r'; + temp[1]='e'; + temp[2]='g'; + temp[3]='\0'; + + mem_len = OF_getproplen(o,phandle, temp); + OF_getprop(o,phandle, temp, buffer, mem_len); + *nomr=mem_len >> 3; + + for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]); + + temp[0]='/'; + temp[1]='c'; + temp[2]='h'; + temp[3]='o'; + temp[4]='s'; + temp[5]='e'; + temp[6]='n'; + temp[7]='\0'; + + phandle=OF_finddevice(o,temp); + + temp[0]='b'; + temp[1]='o'; + temp[2]='o'; + temp[3]='t'; + temp[4]='a'; + temp[5]='r'; + temp[6]='g'; + temp[7]='s'; + temp[8]='\0'; + + mem_len = OF_getproplen(o,phandle, temp); + OF_getprop(o,phandle, temp, buffer, mem_len); + for (i=0; i<=mem_len/4; i++) pointer[i+32]=buffer[i]; + +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/setup-sa1100.S linux.ac/arch/arm/boot/compressed/setup-sa1100.S --- linux-2.4.0/arch/arm/boot/compressed/setup-sa1100.S Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/boot/compressed/setup-sa1100.S Sun Dec 31 14:56:45 2000 @@ -33,13 +33,11 @@ #define UTSR0 0x1c #define UTSR1 0x20 -#define BAUD_DIV_230400 0x000 -#define BAUD_DIV_115200 0x001 -#define BAUD_DIV_57600 0x003 -#define BAUD_DIV_38400 0x005 -#define BAUD_DIV_19200 0x00b -#define BAUD_DIV_9600 0x017 -#define BAUD_DIV BAUD_DIV_9600 +#ifndef CONFIG_SA1100_DEFAULT_BAUDRATE +#define CONFIG_SA1100_DEFAULT_BAUDRATE 9600 +#endif + +#define BAUD_DIV ((230400/CONFIG_SA1100_DEFAULT_BAUDRATE)-1) SCR_loc: .long SYMBOL_NAME(SCR_value) #define GPIO_2_9 0x3fc @@ -92,7 +90,7 @@ bne skip_uart @ UART3 if Assabet is used with Neponset - teq r3, #25 @ if Assabet + teq r3, #MACH_TYPE_ASSABET @ if Assabet tsteq r2, #(1 << 9) @ ... and Neponset present ldreq r0, UART3_BASE beq uart_init diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/boot/compressed/vmlinux.lds.in linux.ac/arch/arm/boot/compressed/vmlinux.lds.in --- linux-2.4.0/arch/arm/boot/compressed/vmlinux.lds.in Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/boot/compressed/vmlinux.lds.in Sun Dec 31 14:57:57 2000 @@ -19,12 +19,13 @@ .text : { _start = .; - head.o(.start) *(.start) - head.o(.text) *(.text) *(.fixup) *(.gnu.warning) + *(.rodata) + *(.glue_7) + *(.glue_7t) input_data = .; piggy.o input_data_end = .; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/config.in linux.ac/arch/arm/config.in --- linux-2.4.0/arch/arm/config.in Thu Nov 16 20:51:28 2000 +++ linux.ac/arch/arm/config.in Sun Dec 31 18:02:14 2000 @@ -352,7 +352,7 @@ source drivers/ieee1394/Config.in -source drivers/i2o/Config.in +source drivers/message/i2o/Config.in mainmenu_option next_comment comment 'ISDN subsystem' diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/Makefile linux.ac/arch/arm/kernel/Makefile --- linux-2.4.0/arch/arm/kernel/Makefile Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/kernel/Makefile Sun Dec 31 14:57:34 2000 @@ -10,16 +10,14 @@ HEAD_OBJ = head-$(PROCESSOR).o ENTRY_OBJ = entry-$(PROCESSOR).o -AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional -AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional +AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) +AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) O_OBJS_arc = dma-arc.o oldlatches.o O_OBJS_rpc = dma-rpc.o O_OBJS_footbridge = dma-footbridge.o isa.o O_OBJS_l7200 = fiq.o -leds-ebsa110 = leds-ebsa110.o - pci-nexuspci = plx90x0.o pci-footbridge = dec21285.o pci-shark = via82c505.o @@ -31,36 +29,28 @@ # Object file lists. -obj-y := arch.o dma.o $(ENTRY_OBJ) irq.o process.o ptrace.o \ - semaphore.o setup.o signal.o sys_arm.o time.o \ - traps.o $(O_OBJS_$(MACHINE)) -obj-m := -obj-n := -obj- := - -export-objs := armksyms.o dma.o ecard.o \ - $(leds-$(MACHINE)) oldlatches.o \ - time.o +obj-y := arch.o dma.o $(ENTRY_OBJ) irq.o process.o ptrace.o \ + semaphore.o setup.o signal.o sys_arm.o time.o traps.o \ + $(O_OBJS_$(MACHINE)) +obj-m := +obj-n := +obj- := + +export-objs := armksyms.o dma.o ecard.o fiq.o oldlatches.o time.o + +no-irq-arch := $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \ + $(CONFIG_ARCH_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) + +ifneq ($(findstring y,$(no-irq-arch)),y) + obj-y += irq-arch.o +endif obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o obj-$(CONFIG_MODULES) += armksyms.o -obj-$(CONFIG_LEDS) += $(leds-$(MACHINE)) obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o - obj-$(CONFIG_PCI) += bios32.o $(pci-$(MACHINE)) $(pci-y) - -# Files that are both resident and modular; remove from modular. - -obj-m := $(filter-out $(obj-y), $(obj-m)) - -# Translate to Rules.make lists. - -O_OBJS := $(filter-out $(export-objs), $(obj-y)) -OX_OBJS := $(filter $(export-objs), $(obj-y)) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) all: kernel.o $(HEAD_OBJ) init_task.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/bios32.c linux.ac/arch/arm/kernel/bios32.c --- linux-2.4.0/arch/arm/kernel/bios32.c Tue Nov 28 01:51:34 2000 +++ linux.ac/arch/arm/kernel/bios32.c Sun Dec 31 15:02:32 2000 @@ -257,11 +257,30 @@ (struct arm_pci_sysdata *)bus->sysdata; struct arm_bus_sysdata *busdata; - if (bus->number < MAX_NR_BUS) - busdata = sysdata->bus + bus->number; - else + if (bus->number >= MAX_NR_BUS) BUG(); + if (bus->self) { + struct pci_dev *dev = bus->self; + int i; + + for (i = 0; i < 3; i++) { + bus->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES + i]; + bus->resource[i]->name = bus->name; + } + bus->resource[0]->start = ioport_resource.start; + bus->resource[0]->end = ioport_resource.end; + bus->resource[0]->flags |= pci_bridge_check_io(dev); + bus->resource[1]->start = iomem_resource.start; + bus->resource[1]->end = iomem_resource.end; + bus->resource[1]->flags |= IORESOURCE_MEM; + + /* Turn off downsteam prefetchable memory address range */ + bus->resource[2]->start = 1024*1024; + bus->resource[2]->end = bus->resource[2]->start - 1; + } + + busdata = sysdata->bus + bus->number; busdata->max_lat = 255; /* @@ -363,10 +382,6 @@ void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) { - ranges->io_start -= bus->resource[0]->start; - ranges->io_end -= bus->resource[0]->start; - ranges->mem_start -= bus->resource[1]->start; - ranges->mem_end -= bus->resource[1]->start; } u8 __init no_swizzle(struct pci_dev *dev, u8 *pin) @@ -442,7 +457,8 @@ hw_pci->init(&sysdata); /* - * Other architectures don't seem to do this... should we? + * Claim the currently allocated resources. This ensures + * that we will not allocate an already inuse region. */ pcibios_claim_resources(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/dma-arc.c linux.ac/arch/arm/kernel/dma-arc.c --- linux-2.4.0/arch/arm/kernel/dma-arc.c Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/kernel/dma-arc.c Sun Dec 31 14:53:48 2000 @@ -40,7 +40,7 @@ memcpy ((void *)0x1c, (void *)&fdc1772_dma_read, &fdc1772_dma_read_end - &fdc1772_dma_read); fdc1772_setupdma(dma->buf.length, dma->buf.address); /* Sets data pointer up */ - enable_irq (64); + enable_fiq(FIQ_FLOPPYDATA); restore_flags(flags); } break; @@ -55,7 +55,7 @@ memcpy ((void *)0x1c, (void *)&fdc1772_dma_write, &fdc1772_dma_write_end - &fdc1772_dma_write); fdc1772_setupdma(dma->buf.length, dma->buf.address); /* Sets data pointer up */ - enable_irq (64); + enable_fiq(FIQ_FLOPPYDATA; restore_flags(flags); } @@ -102,7 +102,7 @@ static void arc_disable_dma(dmach_t channel, dma_t *dma) { - disable_irq(dma->dma_irq); + disable_fiq(dma->dma_irq); } static struct dma_ops arc_floppy_data_dma_ops = { @@ -158,12 +158,12 @@ regs.ARM_r10 = dma->buf.address; regs.ARM_fp = FLOPPYDMA_BASE; set_fiq_regs(®s); - enable_irq(dma->dma_irq); + enable_fiq(dma->dma_irq); } static void a5k_floppy_disable_dma(dmach_t channel, dma_t *dma) { - disable_irq(dma->dma_irq); + disable_fiq(dma->dma_irq); release_fiq(&fh); } @@ -192,15 +192,15 @@ { #if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE) if (machine_is_archimedes()) { - dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY0].dma_irq = FIQ_FLOPPYDATA; dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops; - dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65; + dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 1; dma[DMA_VIRTUAL_FLOPPY1].d_ops = &arc_floppy_cmdend_dma_ops; } #endif #ifdef CONFIG_ARCH_A5K if (machine_is_a5k()) { - dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY0].dma_irq = FIQ_FLOPPYDATA; dma[DMA_VIRTUAL_FLOPPY0].d_ops = &a5k_floppy_dma_ops; } #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/dma-rpc.c linux.ac/arch/arm/kernel/dma-rpc.c --- linux-2.4.0/arch/arm/kernel/dma-rpc.c Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/kernel/dma-rpc.c Sun Dec 31 14:53:48 2000 @@ -42,11 +42,11 @@ #define TRANSFER_SIZE 2 #define CURA (0) -#define ENDA ((IOMD_IO0ENDA - IOMD_IO0CURA) << 2) -#define CURB ((IOMD_IO0CURB - IOMD_IO0CURA) << 2) -#define ENDB ((IOMD_IO0ENDB - IOMD_IO0CURA) << 2) -#define CR ((IOMD_IO0CR - IOMD_IO0CURA) << 2) -#define ST ((IOMD_IO0ST - IOMD_IO0CURA) << 2) +#define ENDA (IOMD_IO0ENDA - IOMD_IO0CURA) +#define CURB (IOMD_IO0CURB - IOMD_IO0CURA) +#define ENDB (IOMD_IO0ENDB - IOMD_IO0CURA) +#define CR (IOMD_IO0CR - IOMD_IO0CURA) +#define ST (IOMD_IO0ST - IOMD_IO0CURA) #define state_prog_a 0 #define state_wait_a 1 @@ -93,14 +93,14 @@ static inline void iomd_setup_dma_a(struct scatterlist *sg, dma_t *dma) { - outl_t(sg->dma_address, dma->dma_base + CURA); - outl_t(sg->length, dma->dma_base + ENDA); + iomd_writel(sg->dma_address, dma->dma_base + CURA); + iomd_writel(sg->length, dma->dma_base + ENDA); } static inline void iomd_setup_dma_b(struct scatterlist *sg, dma_t *dma) { - outl_t(sg->dma_address, dma->dma_base + CURB); - outl_t(sg->length, dma->dma_base + ENDB); + iomd_writel(sg->dma_address, dma->dma_base + CURB); + iomd_writel(sg->length, dma->dma_base + ENDB); } static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) @@ -116,7 +116,7 @@ dma->state = state_wait_a; case state_wait_a: - status = inb_t(dma->dma_base + ST); + status = iomd_readb(dma->dma_base + ST); switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { case DMA_ST_OFL|DMA_ST_INT: iomd_get_next_sg(&dma->cur_sg, dma); @@ -137,7 +137,7 @@ break; case state_wait_b: - status = inb_t(dma->dma_base + ST); + status = iomd_readb(dma->dma_base + ST); switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) { case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB: iomd_get_next_sg(&dma->cur_sg, dma); @@ -193,14 +193,14 @@ PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); } - outb_t(DMA_CR_C, dma_base + CR); + iomd_writeb(DMA_CR_C, dma_base + CR); dma->state = state_prog_a; } if (dma->dma_mode == DMA_MODE_READ) ctrl |= DMA_CR_D; - outb_t(ctrl, dma_base + CR); + iomd_writeb(ctrl, dma_base + CR); enable_irq(dma->dma_irq); } @@ -210,8 +210,8 @@ unsigned int ctrl; disable_irq(dma->dma_irq); - ctrl = inb_t(dma_base + CR); - outb_t(ctrl & ~DMA_CR_E, dma_base + CR); + ctrl = iomd_readb(dma_base + CR); + iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR); } static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle) @@ -227,7 +227,7 @@ else speed = 0; - tcr = inb(IOMD_DMATCR); + tcr = iomd_readb(IOMD_DMATCR); speed &= 3; switch (channel) { @@ -251,7 +251,7 @@ break; } - outb(tcr, IOMD_DMATCR); + iomd_writeb(tcr, IOMD_DMATCR); return speed; } @@ -287,7 +287,7 @@ regs.ARM_r9 = dma->buf.length; regs.ARM_r10 = (unsigned long)dma->buf.address; - regs.ARM_fp = (unsigned long)PCIO_FLOPPYDMABASE; + regs.ARM_fp = FLOPPYDMA_BASE; if (claim_fiq(&fh)) { printk("floppydma: couldn't claim FIQ.\n"); @@ -296,12 +296,12 @@ set_fiq_handler(fiqhandler_start, fiqhandler_length); set_fiq_regs(®s); - enable_irq(dma->dma_irq); + enable_fiq(dma->dma_irq); } static void floppy_disable_dma(dmach_t channel, dma_t *dma) { - disable_irq(dma->dma_irq); + disable_fiq(dma->dma_irq); release_fiq(&fh); } @@ -334,32 +334,32 @@ void __init arch_dma_init(dma_t *dma) { - outb(0, IOMD_IO0CR); - outb(0, IOMD_IO1CR); - outb(0, IOMD_IO2CR); - outb(0, IOMD_IO3CR); + iomd_writeb(0, IOMD_IO0CR); + iomd_writeb(0, IOMD_IO1CR); + iomd_writeb(0, IOMD_IO2CR); + iomd_writeb(0, IOMD_IO3CR); - outb(0xa0, IOMD_DMATCR); + iomd_writeb(0xa0, IOMD_DMATCR); - dma[DMA_0].dma_base = ioaddr(IOMD_IO0CURA); + dma[DMA_0].dma_base = IOMD_IO0CURA; dma[DMA_0].dma_irq = IRQ_DMA0; dma[DMA_0].d_ops = &iomd_dma_ops; - dma[DMA_1].dma_base = ioaddr(IOMD_IO1CURA); + dma[DMA_1].dma_base = IOMD_IO1CURA; dma[DMA_1].dma_irq = IRQ_DMA1; dma[DMA_1].d_ops = &iomd_dma_ops; - dma[DMA_2].dma_base = ioaddr(IOMD_IO2CURA); + dma[DMA_2].dma_base = IOMD_IO2CURA; dma[DMA_2].dma_irq = IRQ_DMA2; dma[DMA_2].d_ops = &iomd_dma_ops; - dma[DMA_3].dma_base = ioaddr(IOMD_IO3CURA); + dma[DMA_3].dma_base = IOMD_IO3CURA; dma[DMA_3].dma_irq = IRQ_DMA3; dma[DMA_3].d_ops = &iomd_dma_ops; - dma[DMA_S0].dma_base = ioaddr(IOMD_SD0CURA); + dma[DMA_S0].dma_base = IOMD_SD0CURA; dma[DMA_S0].dma_irq = IRQ_DMAS0; dma[DMA_S0].d_ops = &iomd_dma_ops; - dma[DMA_S1].dma_base = ioaddr(IOMD_SD1CURA); + dma[DMA_S1].dma_base = IOMD_SD1CURA; dma[DMA_S1].dma_irq = IRQ_DMAS1; dma[DMA_S1].d_ops = &iomd_dma_ops; - dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64; + dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA; dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops; dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops; @@ -367,5 +367,5 @@ * Setup DMA channels 2,3 to be for podules * and channels 0,1 for internal devices */ - outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); + iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/entry-armo.S linux.ac/arch/arm/kernel/entry-armo.S --- linux-2.4.0/arch/arm/kernel/entry-armo.S Mon Sep 18 23:15:24 2000 +++ linux.ac/arch/arm/kernel/entry-armo.S Sun Dec 31 14:54:31 2000 @@ -197,8 +197,7 @@ #endif #define FAULT_CODE_PREFETCH 0x04 #define FAULT_CODE_WRITE 0x02 -#define FAULT_CODE_USER 0x01 - +#define FAULT_CODE_FORCECOW 0x01 #define SVC_SAVE_ALL \ str sp, [sp, #-16]! ;\ @@ -487,7 +486,6 @@ save_user_regs teqp pc, #0x00000003 @ NOT a problem - doesnt change mode mask_pc r0, lr - mov r2, #FAULT_CODE_USER bl Ldata_do b ret_from_exception @@ -499,7 +497,6 @@ tst lr, #0x08000000 teqeqp pc, #0x00000003 @ NOT a problem - doesnt change mode mask_pc r0, lr - mov r2, #0 bl Ldata_do SVC_RESTORE_ALL @@ -510,6 +507,7 @@ Ldata_do: mov r3, sp ldr r4, [r0] @ Get instruction + mov r2, #0 tst r4, #1 << 20 @ Check to see if it is a write instruction orreq r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction mov r1, r4, lsr #22 @ Now branch to the relevent processing routine diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/fiq.c linux.ac/arch/arm/kernel/fiq.c --- linux-2.4.0/arch/arm/kernel/fiq.c Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/kernel/fiq.c Sun Dec 31 14:53:48 2000 @@ -36,12 +36,14 @@ * 6. Goto 3 */ #include +#include #include #include #include #include #include +#include #include #include #include @@ -71,7 +73,7 @@ * - we always relinquish FIQ control * - we always reacquire FIQ control */ -int fiq_def_op(void *ref, int relinquish) +static int fiq_def_op(void *ref, int relinquish) { if (!relinquish) { unprotect_page_0(); @@ -213,6 +215,24 @@ current_fiq = current_fiq->next; while (current_fiq->fiq_op(current_fiq->dev_id, 0)); } + +void enable_fiq(int fiq) +{ + enable_irq(fiq + FIQ_START); +} + +void disable_fiq(int fiq) +{ + disable_irq(fiq + FIQ_START); +} + +EXPORT_SYMBOL(set_fiq_handler); +EXPORT_SYMBOL(set_fiq_regs); +EXPORT_SYMBOL(get_fiq_regs); +EXPORT_SYMBOL(claim_fiq); +EXPORT_SYMBOL(release_fiq); +EXPORT_SYMBOL(enable_fiq); +EXPORT_SYMBOL(disable_fiq); void __init init_FIQ(void) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/process.c linux.ac/arch/arm/kernel/process.c --- linux-2.4.0/arch/arm/kernel/process.c Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/kernel/process.c Sun Dec 31 14:55:03 2000 @@ -92,8 +92,10 @@ void (*idle)(void) = pm_idle; if (!idle) idle = arch_idle; + leds_event(led_idle_start); while (!current->need_resched) idle(); + leds_event(led_idle_end); schedule(); #ifndef CONFIG_NO_PGT_CACHE check_pgt_cache(); @@ -364,20 +366,23 @@ */ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { - extern long sys_exit(int) __attribute__((noreturn)); pid_t __ret; __asm__ __volatile__( - "mov r0, %1 @ kernel_thread sys_clone + "orr r0, %1, %2 @ kernel_thread sys_clone mov r1, #0 "__syscall(clone)" - teq r0, #0 @ if we are the child - moveq fp, #0 @ ensure that fp is zero - mov %0, r0" + movs %0, r0 @ if we are the child + bne 1f + mov fp, #0 @ ensure that fp is zero + mov r0, %4 + mov lr, pc + mov pc, %3 + b sys_exit +1: " : "=r" (__ret) - : "Ir" (flags | CLONE_VM) : "r0", "r1"); - if (__ret == 0) - sys_exit((fn)(arg)); + : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg) + : "r0", "r1", "lr"); return __ret; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/time.c linux.ac/arch/arm/kernel/time.c --- linux-2.4.0/arch/arm/kernel/time.c Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/kernel/time.c Wed Jan 3 16:57:35 2001 @@ -134,32 +134,17 @@ #ifdef CONFIG_MODULES EXPORT_SYMBOL(leds_event); #endif +#endif +#ifdef CONFIG_LEDS_TIMER static void do_leds(void) { -#ifdef CONFIG_LEDS_CPU - { - static int last_pid; + static unsigned int count = 50; - if (current->pid != last_pid) { - last_pid = current->pid; - if (last_pid) - leds_event(led_idle_end); - else - leds_event(led_idle_start); - } + if (--count == 0) { + count = 50; + leds_event(led_timer); } -#endif -#ifdef CONFIG_LEDS_TIMER - { - static unsigned int count = 50; - - if (--count == 0) { - count = 50; - leds_event(led_timer); - } - } -#endif } #else #define do_leds() diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/kernel/traps.c linux.ac/arch/arm/kernel/traps.c --- linux-2.4.0/arch/arm/kernel/traps.c Mon Dec 4 01:48:19 2000 +++ linux.ac/arch/arm/kernel/traps.c Sun Dec 31 14:59:49 2000 @@ -107,7 +107,7 @@ bad = __get_user(val, &((u32 *)addr)[i]); if (!bad) - printk(i == 0 ? "(%0*x) " : "%0*x", width, val); + printk(i == 0 ? "(%0*x) " : "%0*x ", width, val); else { printk("bad PC value."); break; @@ -133,7 +133,7 @@ printk("no frame pointer"); ok = 0; } else if (verify_stack(fp)) { - printk("invalid frame pointer %08lx", fp); + printk("invalid frame pointer 0x%08x", fp); ok = 0; } else if (fp < 4096+(unsigned long)tsk) printk("frame pointer underflow"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/Makefile linux.ac/arch/arm/lib/Makefile --- linux-2.4.0/arch/arm/lib/Makefile Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/Makefile Sun Dec 31 14:57:34 2000 @@ -1,57 +1,57 @@ # # linux/arch/arm/lib/Makefile # -# Copyright (C) 1995-1999 Russell King +# Copyright (C) 1995-2000 Russell King # USE_STANDARD_AS_RULE := true -L_TARGET := lib.a -L_OBJS := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \ - csumpartialcopyuser.o clearbit.o copy_page.o findbit.o \ - memchr.o memcpy.o memset.o memzero.o setbit.o \ - strncpy_from_user.o strnlen_user.o strchr.o strrchr.o \ - testchangebit.o testclearbit.o testsetbit.o uaccess.o - -l-obj-y := -l-obj-n := - -O_TARGET := lib.o -O_OBJS := backtrace.o delay.o - -ifeq ($(CONFIG_ARCH_ACORN),y) - half := n - full := y +L_TARGET := lib.a + +obj-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ + csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ + copy_page.o delay.o findbit.o memchr.o memcpy.o \ + memset.o memzero.o setbit.o strncpy_from_user.o \ + strnlen_user.o strchr.o strrchr.o testchangebit.o \ + testclearbit.o testsetbit.o uaccess.o +obj-m := +obj-n := + +export-objs := io.o + +obj-arc := ecard.o io-acorn.o floppydma.o +obj-rpc := ecard.o io-acorn.o floppydma.o +obj-clps7500 := io-acorn.o +obj-footbridge := io-pcio.o +obj-l7200 := io-acorn.o +obj-nexuspci := io-pcio.o +obj-sa1100 := io-pcio.o +obj-shark := io-shark.o +obj-integrator := io-pcio.o +obj-clps711x := io-shark.o + +obj-y += $(obj-$(MACHINE)) + +ifeq ($(CONFIG_CPU_32v4),y) + v3 := n + v4 := y else - half := y - full := n + v3 := y + v4 := n endif -L_OBJS_arc := ecard.o io-acorn.o floppydma.o -L_OBJS_rpc := ecard.o io-acorn.o floppydma.o -L_OBJS_clps7500 := io-acorn.o -L_OBJS_footbridge := io-pcio.o -L_OBJS_l7200 := io-acorn.o -L_OBJS_nexuspci := io-pcio.o -L_OBJS_sa1100 := io-pcio.o -L_OBJS_shark := io-shark.o -L_OBJS_integrator := io-pcio.o -L_OBJS_clps711x := io-shark.o - -l-obj-y += io-readsb.o io-writesb.o -l-obj-$(full) += io-readsw-armv3.o io-writesw-armv3.o -l-obj-$(half) += io-readsw-armv4.o io-writesw-armv4.o -l-obj-y += io-readsl.o io-writesl.o +obj-y += io-readsb.o io-writesb.o +obj-$(v3) += io-readsw-armv3.o io-writesw-armv3.o io-readsl-armv3.o +obj-$(v4) += io-readsw-armv4.o io-writesw-armv4.o io-readsl-armv4.o +obj-y += io-writesl.o ifeq ($(PROCESSOR),armo) - L_OBJS += uaccess-armo.o + obj-y += uaccess-armo.o endif ifneq ($(MACHINE),ebsa110) - OX_OBJS += io.o + obj-y += io.o endif - -L_OBJS += $(L_OBJS_$(MACHINE)) $(l-obj-y) include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-acorn.S linux.ac/arch/arm/lib/io-acorn.S --- linux-2.4.0/arch/arm/lib/io-acorn.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-acorn.S Sun Dec 31 14:56:20 2000 @@ -60,32 +60,32 @@ */ ENTRY(insw) - teq r2, #0 - RETINSTR(moveq, pc, lr) addr r0 - b __arch_readsw + teq r2, #0 + bne __arch_readsw + RETINSTR(mov, pc, lr) ENTRY(insb) - teq r2, #0 - RETINSTR(moveq, pc, lr) addr r0 - b __arch_readsb + teq r2, #0 + bne __arch_readsb + RETINSTR(mov, pc, lr) @ Purpose: write a block of data from memory to a hardware register. @ Proto : outsw(int to_reg, void *from, int len_in_words); @ Notes : increments from ENTRY(outsw) - teq r2, #0 - RETINSTR(moveq, pc, lr) addr r0 - b __arch_writesw + teq r2, #0 + bne __arch_writesw + RETINSTR(mov, pc, lr) ENTRY(outsb) - teq r2, #0 - RETINSTR(moveq, pc, lr) addr r0 - b __arch_writesb + teq r2, #0 + bne __arch_writesb + RETINSTR(mov, pc, lr) @ Purpose: write a memc register @ Proto : void memc_write(int register, int value); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-pcio.S linux.ac/arch/arm/lib/io-pcio.S --- linux-2.4.0/arch/arm/lib/io-pcio.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-pcio.S Sun Dec 31 14:56:20 2000 @@ -1,4 +1,5 @@ #include +#include #include .equ pcio_high, PCIO_BASE & 0xff000000 @@ -13,26 +14,37 @@ ENTRY(insl) ioaddr r0, r0 - b __arch_readsl + teq r2, #0 + bne __arch_readsl + RETINSTR(mov, pc, lr) ENTRY(outsl) ioaddr r0, r0 - b __arch_writesl - - /* Nobody could say these are optimal, but not to worry. */ + teq r2, #0 + bne __arch_writesl + RETINSTR(mov, pc, lr) ENTRY(outsw) ioaddr r0, r0 - b __arch_writesw + teq r2, #0 + bne __arch_writesw + RETINSTR(mov, pc, lr) ENTRY(insw) ioaddr r0, r0 - b __arch_readsw + teq r2, #0 + bne __arch_readsw + RETINSTR(mov, pc, lr) ENTRY(insb) ioaddr r0, r0 - b __arch_readsb + teq r2, #0 + bne __arch_readsb + RETINSTR(mov, pc, lr) ENTRY(outsb) ioaddr r0, r0 - b __arch_writesb + teq r2, #0 + bne __arch_writesb + RETINSTR(mov, pc, lr) + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-readsb.S linux.ac/arch/arm/lib/io-readsb.S --- linux-2.4.0/arch/arm/lib/io-readsb.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-readsb.S Sun Dec 31 14:56:20 2000 @@ -62,6 +62,7 @@ ldrb ip, [r0] orr r6, r6, ip, lsl #24 stmia r1!, {r3 - r6} + subs r2, r2, #16 bpl .insb_16_lp @@ -88,7 +89,7 @@ stmia r1!, {r3, r4} .insb_no_8: tst r2, #4 - bne .insb_no_4 + beq .insb_no_4 ldrb r3, [r0] ldrb r4, [r0] @@ -101,6 +102,7 @@ .insb_no_4: ands r2, r2, #3 LOADREGS(eqfd, sp!, {r4 - r6, pc}) + cmp r2, #2 ldrb r3, [r0] strb r3, [r1], #1 @@ -108,4 +110,5 @@ strgeb r3, [r1], #1 ldrgtb r3, [r0] strgtb r3, [r1] + LOADREGS(fd, sp!, {r4 - r6, pc}) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-readsl-armv3.S linux.ac/arch/arm/lib/io-readsl-armv3.S --- linux-2.4.0/arch/arm/lib/io-readsl-armv3.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/lib/io-readsl-armv3.S Sun Dec 31 14:56:20 2000 @@ -0,0 +1,76 @@ +/* + * linux/arch/arm/lib/io-readsl-armv3.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +/* + * Note that some reads can be aligned on half-word boundaries. + */ +ENTRY(__arch_readsl) + ands ip, r1, #3 + bne 2f + +1: ldr r3, [r0] + str r3, [r1], #4 + subs r2, r2, #1 + bne 1b + mov pc, lr + +2: cmp ip, #2 + ldr ip, [r0] + blt 4f + bgt 6f + + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 + mov ip, ip, lsr #8 +3: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #16 + strne ip, [r1], #4 + movne ip, r3, lsr #16 + bne 3b + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 + mov pc, lr + +4: strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 + mov ip, ip, lsr #8 +5: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #8 + strne ip, [r1], #4 + movne ip, r3, lsr #24 + bne 5b + strb ip, [r1], #1 + mov pc, lr + +6: strb ip, [r1], #1 + mov ip, ip, lsr #8 +7: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #24 + strne ip, [r1], #4 + movne ip, r3, lsr #8 + bne 7b + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 + mov pc, lr + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-readsl-armv4.S linux.ac/arch/arm/lib/io-readsl-armv4.S --- linux-2.4.0/arch/arm/lib/io-readsl-armv4.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/lib/io-readsl-armv4.S Sun Dec 31 14:56:20 2000 @@ -0,0 +1,68 @@ +/* + * linux/arch/arm/lib/io-readsl-armv4.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +/* + * Note that some reads can be aligned on half-word boundaries. + */ +ENTRY(__arch_readsl) + ands ip, r1, #3 + bne 2f + +1: ldr r3, [r0] + str r3, [r1], #4 + subs r2, r2, #1 + bne 1b + mov pc, lr + +2: cmp ip, #2 + ldr ip, [r0] + blt 4f + bgt 6f + + strh ip, [r1], #2 + mov ip, ip, lsr #16 +3: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #16 + strne ip, [r1], #4 + movne ip, r3, lsr #16 + bne 3b + strh ip, [r1], #2 + mov pc, lr + +4: strb ip, [r1], #1 + mov ip, ip, lsr #8 + strh ip, [r1], #2 + mov ip, ip, lsr #16 +5: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #8 + strne ip, [r1], #4 + movne ip, r3, lsr #24 + bne 5b + strb ip, [r1], #1 + mov pc, lr + +6: strb ip, [r1], #1 + mov ip, ip, lsr #8 +7: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #24 + strne ip, [r1], #4 + movne ip, r3, lsr #8 + bne 7b + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strh ip, [r1], #2 + mov pc, lr + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-readsl.S linux.ac/arch/arm/lib/io-readsl.S --- linux-2.4.0/arch/arm/lib/io-readsl.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-readsl.S Thu Jan 1 01:00:00 1970 @@ -1,65 +0,0 @@ -/* - * linux/arch/arm/lib/io-readsb.S - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include - -ENTRY(__arch_readsl) - ands ip, r1, #3 - bne 2f - -1: ldr r3, [r0] - str r3, [r1], #4 - subs r2, r2, #1 - bne 1b - mov pc, lr - -2: cmp ip, #2 - ldr ip, [r0] - blt 4f - bgt 6f - - strh ip, [r1], #2 - mov ip, ip, lsr #16 -3: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #16 - strne ip, [r1], #4 - movne ip, r3, lsr #16 - bne 3b - strh ip, [r1], #2 - mov pc, lr - -4: strb ip, [r1], #1 - mov ip, ip, lsr #8 - strh ip, [r1], #2 - mov ip, ip, lsr #16 -5: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #8 - strne ip, [r1], #4 - movne ip, r3, lsr #24 - bne 5b - strb ip, [r1], #1 - mov pc, lr - -6: strb ip, [r1], #1 - mov ip, ip, lsr #8 -7: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #24 - strne ip, [r1], #4 - movne ip, r3, lsr #8 - bne 7b - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strh ip, [r1], #2 - mov pc, lr - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-readsw-armv3.S linux.ac/arch/arm/lib/io-readsw-armv3.S --- linux-2.4.0/arch/arm/lib/io-readsw-armv3.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-readsw-armv3.S Sun Dec 31 14:56:20 2000 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/io-readsb.S + * linux/arch/arm/lib/io-readsw-armv3.S * * Copyright (C) 1995-2000 Russell King * @@ -62,8 +62,10 @@ orr r6, r6, lr, lsl #16 stmia r1!, {r3 - r6} + subs r2, r2, #8 bpl .insw_8_lp + tst r2, #7 LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) @@ -97,6 +99,7 @@ strneb r3, [r1], #1 movne r3, r3, lsr #8 strneb r3, [r1] + LOADREGS(fd, sp!, {r4, r5, r6, pc}) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-readsw-armv4.S linux.ac/arch/arm/lib/io-readsw-armv4.S --- linux-2.4.0/arch/arm/lib/io-readsw-armv4.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-readsw-armv4.S Sun Dec 31 14:56:20 2000 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/io-readsb.S + * linux/arch/arm/lib/io-readsw-armv4.S * * Copyright (C) 1995-2000 Russell King * @@ -46,16 +46,18 @@ orr r4, r4, r5, lsl #16 ldrh r5, [r0] - ldrh r6, [r0] - orr r5, r5, r6, lsl #16 + ldrh ip, [r0] + orr r5, r5, ip, lsl #16 ldrh ip, [r0] ldrh lr, [r0] orr ip, ip, lr, lsl #16 stmia r1!, {r3 - r5, ip} + subs r2, r2, #8 bpl .insw_8_lp + tst r2, #7 LOADREGS(eqfd, sp!, {r4, r5, pc}) @@ -84,4 +86,5 @@ .no_insw_2: tst r2, #1 ldrneh r3, [r0] strneh r3, [r1] + LOADREGS(fd, sp!, {r4, r5, pc}) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-writesb.S linux.ac/arch/arm/lib/io-writesb.S --- linux-2.4.0/arch/arm/lib/io-writesb.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-writesb.S Sun Dec 31 14:56:20 2000 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/io-readsb.S + * linux/arch/arm/lib/io-writesb.S * * Copyright (C) 1995-2000 Russell King * @@ -13,7 +13,7 @@ .outsb_align: rsb ip, ip, #4 cmp ip, r2 - mov ip, r2 + movgt ip, r2 cmp ip, #2 ldrb r3, [r1], #1 strb r3, [r0] @@ -34,6 +34,7 @@ bmi .outsb_no_16 .outsb_16_lp: ldmia r1!, {r3 - r6} + strb r3, [r0] mov r3, r3, lsr #8 strb r3, [r0] @@ -65,6 +66,7 @@ strb r6, [r0] mov r6, r6, lsr #8 strb r6, [r0] + subs r2, r2, #16 bpl .outsb_16_lp @@ -74,7 +76,8 @@ .outsb_no_16: tst r2, #8 beq .outsb_no_8 - ldmia r1, {r3, r4} + ldmia r1!, {r3, r4} + strb r3, [r0] mov r3, r3, lsr #8 strb r3, [r0] @@ -92,7 +95,7 @@ strb r4, [r0] .outsb_no_8: tst r2, #4 - bne .outsb_no_4 + beq .outsb_no_4 ldr r3, [r1], #4 strb r3, [r0] @@ -105,6 +108,7 @@ .outsb_no_4: ands r2, r2, #3 LOADREGS(eqfd, sp!, {r4 - r6, pc}) + cmp r2, #2 ldrb r3, [r1], #1 strb r3, [r0] @@ -112,4 +116,5 @@ strgeb r3, [r0] ldrgtb r3, [r1] strgtb r3, [r0] + LOADREGS(fd, sp!, {r4 - r6, pc}) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-writesl.S linux.ac/arch/arm/lib/io-writesl.S --- linux-2.4.0/arch/arm/lib/io-writesl.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-writesl.S Sun Dec 31 14:56:20 2000 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/io-readsb.S + * linux/arch/arm/lib/io-writesl.S * * Copyright (C) 1995-2000 Russell King * diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-writesw-armv3.S linux.ac/arch/arm/lib/io-writesw-armv3.S --- linux-2.4.0/arch/arm/lib/io-writesw-armv3.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-writesw-armv3.S Sun Dec 31 14:56:20 2000 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/io-readsb.S + * linux/arch/arm/lib/io-writesw-armv3.S * * Copyright (C) 1995-2000 Russell King * @@ -39,6 +39,7 @@ subs r2, r2, #8 bmi .no_outsw_8 + .outsw_8_lp: ldmia r1!, {r3, r4, r5, r6} mov ip, r3, lsl #16 @@ -75,6 +76,7 @@ subs r2, r2, #8 bpl .outsw_8_lp + tst r2, #7 LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) @@ -121,5 +123,3 @@ strne ip, [r0] LOADREGS(fd, sp!, {r4, r5, r6, pc}) - - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/lib/io-writesw-armv4.S linux.ac/arch/arm/lib/io-writesw-armv4.S --- linux-2.4.0/arch/arm/lib/io-writesw-armv4.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/lib/io-writesw-armv4.S Sun Dec 31 14:56:20 2000 @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/io-readsb.S + * linux/arch/arm/lib/io-writesw-armv4.S * * Copyright (C) 1995-2000 Russell King * @@ -32,11 +32,11 @@ tst r1, #3 bne .outsw_align + stmfd sp!, {r4, r5, lr} + subs r2, r2, #8 bmi .no_outsw_8 - stmfd sp!, {r4, r5, lr} - .outsw_8_lp: ldmia r1!, {r3, r4, r5, ip} strh r3, [r0] @@ -54,26 +54,31 @@ subs r2, r2, #8 bpl .outsw_8_lp - ldmfd sp!, {r4, r5, lr} + tst r2, #7 - RETINSTR(moveq, pc, lr) + LOADREGS(eqfd, sp!, {r4, r5, pc}) .no_outsw_8: tst r2, #4 - ldmneia r1!, {r3, ip} - strneh r3, [r0] - movne r3, r3, lsr #16 - strneh r3, [r0] - strneh ip, [r0] - movne ip, ip, lsr #16 - strneh ip, [r0] - tst r2, #2 - ldrne r3, [r1], #4 - strneh r3, [r0] - movne r3, r3, lsr #16 - strneh r3, [r0] - tst r2, #1 + beq .no_outsw_4 + + ldmia r1!, {r3, ip} + strh r3, [r0] + mov r3, r3, lsr #16 + strh r3, [r0] + strh ip, [r0] + mov ip, ip, lsr #16 + strh ip, [r0] + +.no_outsw_4: tst r2, #2 + beq .no_outsw_2 + + ldr r3, [r1], #4 + strh r3, [r0] + mov r3, r3, lsr #16 + strh r3, [r0] + +.no_outsw_2: tst r2, #1 ldrneh r3, [r1] strneh r3, [r0] - RETINSTR(mov, pc, lr) - + LOADREGS(fd, sp!, {r4, r5, pc}) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mach-sa1100/Makefile linux.ac/arch/arm/mach-sa1100/Makefile --- linux-2.4.0/arch/arm/mach-sa1100/Makefile Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mach-sa1100/Makefile Sun Dec 31 14:57:34 2000 @@ -20,15 +20,4 @@ obj-$(CONFIG_LEDS) += leds.o -# Files that are both resident and modular; remove from modular. - -obj-m := $(filter-out $(obj-y), $(obj-m)) - -# Translate to Rules.make lists. - -O_OBJS := $(filter-out $(export-objs), $(obj-y)) -OX_OBJS := $(filter $(export-objs), $(obj-y)) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) - include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mach-sa1100/hw.c linux.ac/arch/arm/mach-sa1100/hw.c --- linux-2.4.0/arch/arm/mach-sa1100/hw.c Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mach-sa1100/hw.c Wed Jan 3 17:00:36 2001 @@ -90,12 +90,12 @@ void clr_bitsy_egpio(unsigned long x) { bitsy_egpio &= ~x; - *(volatile int *)0xdc000000 = bitsy_egpio; + BITSY_EGPIO = bitsy_egpio; } void set_bitsy_egpio(unsigned long x) { bitsy_egpio |= x; - *(volatile int *)0xdc000000 = bitsy_egpio; + BITSY_EGPIO = bitsy_egpio; } EXPORT_SYMBOL(clr_bitsy_egpio); EXPORT_SYMBOL(set_bitsy_egpio); @@ -119,8 +119,8 @@ /* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: * (SA-1110 Developer's Manual, section 9.1.2.1) */ - GAFR |= GPIO_GPIO27; - GPDR |= GPIO_GPIO27; + GAFR |= GPIO_32_768kHz; + GPDR |= GPIO_32_768kHz; TUCR = TUCR_3_6864MHz; /* Now, set up the PLL and RCLK in the SA-1111: */ @@ -133,32 +133,32 @@ * using the SKPCR. */ - { - /* - * SA1111 DMA bus master setup + /* If the system is going to use the SA-1111 DMA engines, set up + * the memory bus request/grant pins. Also configure the shared + * memory controller on the SA-1111 (SA-1111 Developer's Manual, + * section 3.2.3) and power up the DMA bus clock: */ - int cas; + if(machine_is_assabet()){ - /* SA1111 side */ - switch ( (MDCNFG>>12) & 0x03 ) { - case 0x02: - cas = 0; break; - case 0x03: - cas = 1; break; - default: - cas = 1; break; - } - SMCR = 1 /* 1: memory is SDRAM */ - | ( 1 << 1 ) /* 1:MBGNT is enable */ - | ( ((MDCNFG >> 4) & 0x07) << 2 ) /* row address lines */ - | ( cas << 5 ); /* CAS latency */ - - /* SA1110 side */ - GPDR |= 1<<21; - GPDR &= ~(1<<22); - GAFR |= ( (1<<21) | (1<<22) ); + GAFR |= (GPIO_MBGNT | GPIO_MBREQ); + GPDR |= GPIO_MBGNT; + GPDR &= ~GPIO_MBREQ; + TUCR |= TUCR_MR; + + /* Assabet is populated by default with two Samsung KM416S8030T-G8 + * 128Mb SDRAMs, which are organized as 12-bit (row addr) x 9-bit + * (column addr), according to the data sheet. Apparently, the + * bank selects factor into the row address, as Angel sets up the + * SA-1110 to use 14x9 addresses. The SDRAM datasheet specifies + * that when running at 100-125MHz, the CAS latency for -8 parts + * is 3 cycles, which is consistent with Angel. + */ + + SMCR = (SMCR_DTIM | SMCR_MBGE | + FInsrt(FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), SMCR_DRAC) | + ((FExtr(MDCNFG, MDCNFG_SA1110_TDL0)==3) ? SMCR_CLAT : 0)); - TUCR |= (1<<10); + SKPCR |= SKPCR_DCLKEN; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mach-shark/Makefile linux.ac/arch/arm/mach-shark/Makefile --- linux-2.4.0/arch/arm/mach-shark/Makefile Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mach-shark/Makefile Sun Dec 31 14:57:34 2000 @@ -5,6 +5,8 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). +USE_STANDARD_AS_RULE := true + O_TARGET := shark.o # Object file lists. @@ -17,16 +19,5 @@ export-objs := #obj-$(CONFIG_LEDS) += leds.o - -# Files that are both resident and modular; remove from modular. - -obj-m := $(filter-out $(obj-y), $(obj-m)) - -# Translate to Rules.make lists. - -O_OBJS := $(filter-out $(export-objs), $(obj-y)) -OX_OBJS := $(filter $(export-objs), $(obj-y)) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/Makefile linux.ac/arch/arm/mm/Makefile --- linux-2.4.0/arch/arm/mm/Makefile Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mm/Makefile Sun Dec 31 14:57:34 2000 @@ -9,12 +9,11 @@ USE_STANDARD_AS_RULE := true -EXTRA_AFLAGS := -traditional O_TARGET := mm.o # Object file lists. -obj-y := extable.o fault-$(PROCESSOR).o init.o \ +obj-y := extable.o fault-common.o fault-$(PROCESSOR).o init.o \ mm-$(PROCESSOR).o small_page.o obj-m := obj-n := @@ -22,10 +21,10 @@ export-objs := proc-syms.o p-$(CONFIG_CPU_26) += proc-arm2,3.o -p-$(CONFIG_CPU_ARM6) += proc-arm6,7.o -p-$(CONFIG_CPU_ARM7) += proc-arm6,7.o -p-$(CONFIG_CPU_ARM720) += proc-arm720.o -p-$(CONFIG_CPU_ARM920) += proc-arm920.o +p-$(CONFIG_CPU_ARM610) += proc-arm6,7.o +p-$(CONFIG_CPU_ARM710) += proc-arm6,7.o +p-$(CONFIG_CPU_ARM720T) += proc-arm720.o +p-$(CONFIG_CPU_ARM920T) += proc-arm920.o p-$(CONFIG_CPU_ARM10) += proc-arm10.o p-$(CONFIG_CPU_SA110) += proc-sa110.o p-$(CONFIG_CPU_SA1100) += proc-sa110.o @@ -37,29 +36,16 @@ # Integrator follows "new style" # Soon, others will do too, and we can get rid of this -MMMACH := mm-$(MACHINE).o +MMMACH := mm-$(MACHINE).c ifeq ($(MMMACH),$(wildcard $(MMMACH))) -obj-$(CONFIG_CPU_32) += $(MMMACH) +obj-$(CONFIG_CPU_32) += $(MMMACH:.c=.o) endif obj-y += $(sort $(p-y)) -# Files that are both resident and modular; remove from modular. - -obj-m := $(filter-out $(obj-y), $(obj-m)) - -# Translate to Rules.make lists. - -O_OBJS := $(filter-out $(export-objs), $(obj-y)) -OX_OBJS := $(filter $(export-objs), $(obj-y)) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) - include $(TOPDIR)/Rules.make # Special dependencies -fault-armv.o: fault-common.c -fault-armo.o: fault-common.c proc-arm2,3.o: ../lib/constants.h proc-arm6,7.o: ../lib/constants.h proc-arm720.o: ../lib/constants.h diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/fault-armo.c linux.ac/arch/arm/mm/fault-armo.c --- linux-2.4.0/arch/arm/mm/fault-armo.c Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mm/fault-armo.c Sun Dec 31 14:54:31 2000 @@ -23,14 +23,20 @@ #include #include -#define FAULT_CODE_FORCECOW 0x80 +#define FAULT_CODE_LDRSTRPOST 0x80 +#define FAULT_CODE_LDRSTRPRE 0x40 +#define FAULT_CODE_LDRSTRREG 0x20 +#define FAULT_CODE_LDMSTM 0x10 +#define FAULT_CODE_LDCSTC 0x08 #define FAULT_CODE_PREFETCH 0x04 #define FAULT_CODE_WRITE 0x02 +#define FAULT_CODE_FORCECOW 0x01 #define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW)) #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE)) -#include "fault-common.c" +extern int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs); +extern void show_pte(struct mm_struct *mm, unsigned long addr); /* * Handle a data abort. Note that we have to handle a range of addresses diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/fault-armv.c linux.ac/arch/arm/mm/fault-armv.c --- linux-2.4.0/arch/arm/mm/fault-armv.c Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mm/fault-armv.c Sun Dec 31 14:54:31 2000 @@ -27,27 +27,9 @@ #include #include -#define FAULT_CODE_READ 0x02 - -#define DO_COW(m) (!((m) & FAULT_CODE_READ)) -#define READ_FAULT(m) ((m) & FAULT_CODE_READ) - extern void die_if_kernel(const char *str, struct pt_regs *regs, int err); - -#include "fault-common.c" - -#ifdef DEBUG -static int sp_valid(unsigned long *sp) -{ - unsigned long addr = (unsigned long) sp; - - if (addr >= 0xb0000000 && addr < 0xd0000000) - return 1; - if (addr >= 0x03ff0000 && addr < 0x04000000) - return 1; - return 0; -} -#endif +extern void show_pte(struct mm_struct *mm, unsigned long addr); +extern int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs); #ifdef CONFIG_ALIGNMENT_TRAP /* @@ -178,6 +160,15 @@ eaddr -= offset.un; } + /* + * This is a "hint" - we already have eaddr worked out by the + * processor for us. + */ + if (addr != eaddr) + printk(KERN_ERR "LDRHSTRH: PC = %08lx, instr = %08x, " + "addr = %08lx, eaddr = %08lx\n", + instruction_pointer(regs), instr, addr, eaddr); + if (LDST_L_BIT(instr)) regs->uregs[rd] = get_unaligned((unsigned short *)eaddr); else @@ -253,8 +244,15 @@ } } -if (addr != eaddr) -printk("PC = %08lx, instr = %08x, addr = %08lx, eaddr = %08lx\n", instruction_pointer(regs), instr, addr, eaddr); + /* + * This is a "hint" - we already have eaddr worked out by the + * processor for us. + */ + if (addr != eaddr) + printk(KERN_ERR "LDRSTR: PC = %08lx, instr = %08x, " + "addr = %08lx, eaddr = %08lx\n", + instruction_pointer(regs), instr, addr, eaddr); + if (LDST_L_BIT(instr)) { regs->uregs[rd] = get_unaligned((unsigned long *)eaddr); if (rd == 15) @@ -284,6 +282,15 @@ if (!LDST_U_BIT(instr)) eaddr -= nr_regs; + /* + * This is a "hint" - we already have eaddr worked out by the + * processor for us. + */ + if (addr != eaddr) + printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08x, " + "addr = %08lx, eaddr = %08lx\n", + instruction_pointer(regs), instr, addr, eaddr); + if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) || (LDST_U_BIT(instr) && LDST_P_BIT(instr))) eaddr += 4; @@ -322,39 +329,39 @@ #endif -#ifdef CONFIG_DEBUG_USER - +/* + * Some section permission faults need to be handled gracefully, for + * instance, when they happen due to a __{get,put}_user during an oops). + * In this case, we should return an error to the __{get,put}_user caller + * instead of causing another oops. We should also fixup this fault as + * the user could pass a pointer to a section to the kernel. + */ static int do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs) { + unsigned long fixup; + if (user_mode(regs)) { +#ifdef CONFIG_DEBUG_USER printk("%s: permission fault on section, " "address=0x%08lx, code %d\n", current->comm, addr, error_code); +#endif + goto fail; + } + + fixup = search_exception_table(instruction_pointer(regs)); + if (fixup != 0) { #ifdef DEBUG - { - unsigned int i, j; - unsigned long *sp; - - sp = (unsigned long *) (regs->ARM_sp - 128); - for (j = 0; j < 20 && sp_valid(sp); j++) { - printk("%p: ", sp); - for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++) - printk("%08lx ", *sp); - printk("\n"); - } - show_regs(regs); - c_backtrace(regs->ARM_fp, regs->ARM_cpsr); - } + printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", + tsk->comm, regs->ARM_pc, addr, fixup); #endif + regs->ARM_pc = fixup; + return 0; } +fail: return 1; /* not fixed up */ } -#else - -#define do_sect_fault NULL - -#endif static const struct fsr_info { int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs); @@ -382,18 +389,19 @@ /* * Currently dropped down to debug level */ -#define BUG_PROC_MSG \ - KERN_DEBUG "Weird data abort (%08X).\n" \ - KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for " \ - "more information\n" - asmlinkage void do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr) { const struct fsr_info *inf = fsr_info + (fsr & 15); +#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) if (addr == regs->ARM_pc) - goto weirdness; + goto sa1_weirdness; +#endif +#if defined(CONFIG_CPU_ARM720T) && defined(CONFIG_ALIGNMENT_TRAP) + if (addr & 3 && (fsr & 13) != 1) + goto arm720_weirdness; +#endif if (!inf->fn) goto bad; @@ -409,26 +417,51 @@ die_if_kernel("Oops", regs, 0); return; -weirdness: +#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) +sa1_weirdness: if (user_mode(regs)) { static int first = 1; if (first) - /* - * I want statistical information on this problem, - * but we don't want to hastle the users too much. - */ - printk(BUG_PROC_MSG, fsr); + printk(KERN_DEBUG "Weird data abort detected\n"); first = 0; return; } if (!inf->fn || inf->fn(addr, error_code, regs)) goto bad; + return; +#endif +#if defined(CONFIG_CPU_ARM720T) && defined(CONFIG_ALIGNMENT_TRAP) +arm720_weirdness: + if (!user_mode(regs)) { + unsigned long instr; + + instr = *(unsigned long *)instruction_pointer(regs); + + if ((instr & 0x04400000) != 0x04400000) { + static int first = 1; + if (first) + printk("Mis-reported alignment fault at " + "0x%08lx, fsr 0x%02x, code 0x%02x, " + "PC = 0x%08lx, instr = 0x%08lx\n", + addr, fsr, error_code, regs->ARM_pc, + instr); + first = 0; + cpu_tlb_invalidate_all(); + cpu_cache_clean_invalidate_all(); + return; + } + } + + if (!inf->fn || inf->fn(addr, error_code, regs)) + goto bad; + return; +#endif } asmlinkage int do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) { - do_page_fault(addr, FAULT_CODE_READ, regs); + do_page_fault(addr, 0, regs); return 1; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/fault-common.c linux.ac/arch/arm/mm/fault-common.c --- linux-2.4.0/arch/arm/mm/fault-common.c Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/mm/fault-common.c Sun Dec 31 14:54:31 2000 @@ -9,8 +9,41 @@ * published by the Free Software Foundation. */ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_CPU_26 +#define FAULT_CODE_WRITE 0x02 +#define FAULT_CODE_FORCECOW 0x01 +#define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW)) +#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE)) +#else +/* + * On 32-bit processors, we define "mode" to be zero when reading, + * non-zero when writing. This now ties up nicely with the polarity + * of the 26-bit machines, and also means that we avoid the horrible + * gcc code for "int val = !other_val;". + */ +#define DO_COW(m) (m) +#define READ_FAULT(m) (!(m)) +#endif -extern void die(const char *msg, struct pt_regs *regs, int err); +NORET_TYPE void die(const char *msg, struct pt_regs *regs, int err) ATTRIB_NORET; /* * This is useful to dump out the page tables associated with @@ -60,7 +93,9 @@ printk("\n"); } -static int __do_page_fault(struct mm_struct *mm, unsigned long addr, int mode, struct task_struct *tsk) +static int +__do_page_fault(struct mm_struct *mm, unsigned long addr, int mode, + struct task_struct *tsk) { struct vm_area_struct *vma; int fault, mask; @@ -159,7 +194,7 @@ return -2; } -static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) +int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) { struct task_struct *tsk; struct mm_struct *mm; @@ -278,8 +313,10 @@ * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ - printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", - (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); + printk(KERN_ALERT + "Unable to handle kernel %s at virtual address %08lx\n", + (addr < PAGE_SIZE) ? "NULL pointer dereference" : + "paging request", addr); show_pte(mm, addr); die("Oops", regs, mode); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/init.c linux.ac/arch/arm/mm/init.c --- linux-2.4.0/arch/arm/mm/init.c Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/mm/init.c Wed Jan 3 17:00:04 2001 @@ -49,7 +49,7 @@ #define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *)) static unsigned long totalram_pages; -pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern char _stext, _text, _etext, _end, __init_begin, __init_end; /* @@ -418,7 +418,7 @@ if (machine_is_archimedes() || machine_is_a5k()) reserve_bootmem_node(pgdat, 0x02000000, 0x00080000); if (machine_is_p720t()) - reserve_bootmem_node(pgdat, 0xc0000000, 0x00014000); + reserve_bootmem_node(pgdat, PAGE_OFFSET, 0x00014000); } /* @@ -450,8 +450,28 @@ initrd_node = check_initrd(mi); map_pg = bootmap_pfn; - - for (node = 0; node < numnodes; node++, np++) { + + /* + * Initialise the bootmem nodes. + * + * What we really want to do is: + * + * unmap_all_regions_except_kernel(); + * for_each_node_in_reverse_order(node) { + * map_node(node); + * allocate_bootmem_map(node); + * init_bootmem_node(node); + * free_bootmem_node(node); + * } + * + * but this is a 2.5-type change. For now, we just set + * the nodes up in reverse order. + * + * (we could also do with rolling bootmem_init and paging_init + * into one generic "memory_init" type function). + */ + np += numnodes - 1; + for (node = numnodes - 1; node >= 0; node--, np--) { /* * If there are no pages in this node, ignore it. * Note that node 0 must always have some pages. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/mm-armv.c linux.ac/arch/arm/mm/mm-armv.c --- linux-2.4.0/arch/arm/mm/mm-armv.c Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/mm/mm-armv.c Sun Dec 31 14:59:49 2000 @@ -275,7 +275,7 @@ off = md->physical - virt; length = md->length; - while ((virt & 1048575 || (virt + off) & 1048575) && length >= PAGE_SIZE) { + while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) { alloc_init_page(virt, virt + off, md->domain, prot_pte); virt += PAGE_SIZE; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/proc-arm6,7.S linux.ac/arch/arm/mm/proc-arm6,7.S --- linux-2.4.0/arch/arm/mm/proc-arm6,7.S Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mm/proc-arm6,7.S Sun Dec 31 14:54:31 2000 @@ -7,10 +7,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * MMU functions for ARM6 - * * These are the low level assembler for performing cache and TLB - * functions on the ARM6 & ARM7. + * functions on the ARM610 & ARM710. */ #include #include @@ -105,9 +103,9 @@ ENTRY(cpu_arm6_data_abort) ldr r4, [r0] @ read instruction causing problem - mov r1, r4, lsr #19 @ r1 b1 = L + tst r4, r4, lsr #21 @ C = bit 20 + sbc r1, r1, r1 @ r1 = C - 1 and r2, r4, #14 << 24 - and r1, r1, #2 @ check read/write bit teq r2, #8 << 24 @ was it ldm/stm bne Ldata_simple @@ -138,9 +136,9 @@ ENTRY(cpu_arm7_data_abort) ldr r4, [r0] @ read instruction causing problem - mov r1, r4, lsr #19 @ r1 b1 = L + tst r4, r4, lsr #21 @ C = bit 20 + sbc r1, r1, r1 @ r1 = C - 1 and r2, r4, #15 << 24 - and r1, r1, #2 @ check read/write bit add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine movs pc, lr diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/proc-arm720.S linux.ac/arch/arm/mm/proc-arm720.S --- linux-2.4.0/arch/arm/mm/proc-arm720.S Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/mm/proc-arm720.S Sun Dec 31 14:54:31 2000 @@ -144,9 +144,9 @@ ENTRY(cpu_arm720_data_abort) ldr r4, [r0] @ read instruction causing problem - mov r1, r4, lsr #19 @ r1 b1 = L + tst r4, r4, lsr #21 @ C = bit 20 + sbc r1, r1, r1 @ r1 = C - 1 and r2, r4, #15 << 24 - and r1, r1, #2 @ check read/write bit add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine movs pc, lr @@ -283,23 +283,11 @@ ldmfd sp!, {pc} /* - * Function: arm720_proc_do_idle (void) - * - * Params : r0 = call type: - * 0 = slow idle - * 1 = fast idle - * 2 = switch to slow processor clock - * 3 = switch to fast processor clock - * + * Function: arm720_proc_do_idle(void) + * Params : r0 = unused * Purpose : put the processer in proper idle mode */ ENTRY(cpu_arm720_do_idle) -#if 0 /* FIXME: is this part of the processor? */ - ldr r2, =IO_BASE @ Virt addr of IO - add r2, r2, #0x00050000 @ Start of PMU regs - mov r1, #0x01 @ Idle mode - str r1, [r2, #4] -#endif mov pc, lr /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/proc-arm920.S linux.ac/arch/arm/mm/proc-arm920.S --- linux-2.4.0/arch/arm/mm/proc-arm920.S Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mm/proc-arm920.S Sun Dec 31 14:54:31 2000 @@ -68,9 +68,9 @@ ENTRY(cpu_arm920_data_abort) ldr r1, [r0] @ read aborted instruction mrc p15, 0, r0, c6, c0, 0 @ get FAR - mov r1, r1, lsr #19 @ b1 = L + tst r1, r1, lsr #21 @ C = bit 20 mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r1, r1, #2 + sbc r1, r1, r1 @ r1 = C - 1 and r3, r3, #255 mov pc, lr @@ -330,7 +330,7 @@ mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain WB ENTRY(cpu_arm920_icache_invalidate_page) - /* why no invalidate I cache --rmk */ + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache mov pc, lr diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/mm/proc-sa110.S linux.ac/arch/arm/mm/proc-sa110.S --- linux-2.4.0/arch/arm/mm/proc-sa110.S Mon Sep 18 23:15:25 2000 +++ linux.ac/arch/arm/mm/proc-sa110.S Sun Dec 31 14:54:31 2000 @@ -83,9 +83,9 @@ ENTRY(cpu_sa1100_data_abort) ldr r1, [r0] @ read aborted instruction mrc p15, 0, r0, c6, c0, 0 @ get FAR - mov r1, r1, lsr #19 @ b1 = L + tst r1, r1, lsr #21 @ C = bit 20 mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r1, r1, #2 + sbc r1, r1, r1 @ r1 = C - 1 and r3, r3, #255 mov pc, lr diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/nwfpe/Makefile linux.ac/arch/arm/nwfpe/Makefile --- linux-2.4.0/arch/arm/nwfpe/Makefile Sun Aug 13 17:54:15 2000 +++ linux.ac/arch/arm/nwfpe/Makefile Sun Dec 31 14:57:34 2000 @@ -6,27 +6,27 @@ USE_STANDARD_AS_RULE := true -NWFPE_OBJS := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \ - fpmodule.o fpopcode.o softfloat.o \ - single_cpdo.o double_cpdo.o extended_cpdo.o +O_TARGET := math-emu.o -ifeq ($(CONFIG_CPU_26),y) -NWFPE_OBJS += entry26.o -else -NWFPE_OBJS += entry.o -endif +obj-y := +obj-m := +obj-n := + +list-multi := nwfpe.o -ifeq ($(CONFIG_NWFPE),y) -O_TARGET := math-emu.o -O_OBJS = $(NWFPE_OBJS) +obj-$(CONFIG_NWFPE) += nwfpe.o + +nwfpe-objs := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \ + fpmodule.o fpopcode.o softfloat.o \ + single_cpdo.o double_cpdo.o extended_cpdo.o + +ifeq ($(CONFIG_CPU_26),y) +nwfpe-objs += entry26.o else - ifeq ($(CONFIG_NWFPE),m) - M_OBJS = nwfpe.o - MI_OBJS = $(NWFPE_OBJS) - endif +nwfpe-objs += entry.o endif include $(TOPDIR)/Rules.make -nwfpe.o: $(MI_OBJS) $(MIX_OBJS) - $(LD) $(LD_RFLAG) -r -o $@ $(MI_OBJS) $(MIX_OBJS) +nwfpe.o: $(nwfpe-objs) + $(LD) -r -o $@ $(nwfpe-objs) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/vmlinux-armo.lds.in linux.ac/arch/arm/vmlinux-armo.lds.in --- linux-2.4.0/arch/arm/vmlinux-armo.lds.in Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/vmlinux-armo.lds.in Sun Dec 31 14:57:57 2000 @@ -47,6 +47,8 @@ *(.gnu.warning) *(.text.lock) /* out-of-line lock text */ *(.rodata) + *(.glue_7) + *(.glue_7t) *(.kstrtab) . = ALIGN(16); /* Exception table */ __start___ex_table = .; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/arm/vmlinux-armv.lds.in linux.ac/arch/arm/vmlinux-armv.lds.in --- linux-2.4.0/arch/arm/vmlinux-armv.lds.in Tue Nov 28 01:07:59 2000 +++ linux.ac/arch/arm/vmlinux-armv.lds.in Sun Dec 31 14:57:57 2000 @@ -42,6 +42,8 @@ *(.gnu.warning) *(.text.lock) /* out-of-line lock text */ *(.rodata) + *(.glue_7) + *(.glue_7t) *(.kstrtab) . = ALIGN(16); __start___ex_table = .; /* Exception table */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/i386/config.in linux.ac/arch/i386/config.in --- linux-2.4.0/arch/i386/config.in Fri Dec 29 22:35:47 2000 +++ linux.ac/arch/i386/config.in Sun Dec 31 22:29:20 2000 @@ -293,9 +293,11 @@ fi endmenu +source drivers/message/fusion/Config.in + source drivers/ieee1394/Config.in -source drivers/i2o/Config.in +source drivers/message/i2o/Config.in if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/i386/kernel/Makefile linux.ac/arch/i386/kernel/Makefile --- linux-2.4.0/arch/i386/kernel/Makefile Fri Dec 29 22:35:47 2000 +++ linux.ac/arch/i386/kernel/Makefile Sat Dec 30 01:04:51 2000 @@ -41,4 +41,9 @@ obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) + include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/i386/kernel/microcode.c linux.ac/arch/i386/kernel/microcode.c --- linux-2.4.0/arch/i386/kernel/microcode.c Mon Dec 11 21:42:08 2000 +++ linux.ac/arch/i386/kernel/microcode.c Wed Jan 3 16:47:22 2001 @@ -126,6 +126,7 @@ printk(KERN_ERR "microcode: failed to devfs_register()\n"); goto out; } + error = 0; printk(KERN_INFO "IA-32 Microcode Update Driver: v%s \n", MICROCODE_VERSION); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ia64/config.in linux.ac/arch/ia64/config.in --- linux-2.4.0/arch/ia64/config.in Thu Jan 4 20:50:17 2001 +++ linux.ac/arch/ia64/config.in Fri Jan 5 00:10:23 2001 @@ -123,7 +123,7 @@ source drivers/mtd/Config.in source drivers/pnp/Config.in source drivers/block/Config.in -source drivers/i2o/Config.in +source drivers/message/i2o/Config.in source drivers/md/Config.in mainmenu_option next_comment diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/mips/config.in linux.ac/arch/mips/config.in --- linux-2.4.0/arch/mips/config.in Thu Nov 16 20:51:28 2000 +++ linux.ac/arch/mips/config.in Sun Dec 31 18:02:39 2000 @@ -233,7 +233,7 @@ if [ "$CONFIG_DECSTATION" != "y" -a \ "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/i2o/Config.in + source drivers/message/i2o/Config.in fi if [ "$CONFIG_NET" = "y" ]; then diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/mips64/config.in linux.ac/arch/mips64/config.in --- linux-2.4.0/arch/mips64/config.in Wed Nov 29 05:42:04 2000 +++ linux.ac/arch/mips64/config.in Sun Dec 31 18:02:48 2000 @@ -164,7 +164,7 @@ fi endmenu -source drivers/i2o/Config.in +source drivers/message/i2o/Config.in if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/boot/Makefile linux.ac/arch/ppc/boot/Makefile --- linux-2.4.0/arch/ppc/boot/Makefile Tue Jun 20 01:59:35 2000 +++ linux.ac/arch/ppc/boot/Makefile Wed Jan 3 17:08:29 2001 @@ -25,10 +25,6 @@ IOFF = 0 ISZ = 0 -ifeq ($(CONFIG_ALL_PPC),y) -CONFIG_PREP=y -endif - ifeq ($(CONFIG_SMP),y) TFTPIMAGE=/tftpboot/zImage.prep.smp$(MSIZE) else @@ -82,7 +78,7 @@ rm zvmlinux.initrd.tmp zImage: zvmlinux mkprep sImage -ifdef CONFIG_PREP +ifdef CONFIG_ALL_PPC ./mkprep -pbp zvmlinux zImage endif ifdef CONFIG_APUS @@ -96,7 +92,7 @@ endif zImage.initrd: zvmlinux.initrd mkprep -ifdef CONFIG_PREP +ifdef CONFIG_ALL_PPC ./mkprep -pbp zvmlinux.initrd zImage.initrd endif @@ -128,7 +124,7 @@ $(HOSTCC) -o mkprep mkprep.c znetboot : zImage -ifdef CONFIG_PREP +ifdef CONFIG_ALL_PPC cp zImage $(TFTPIMAGE) endif ifdef CONFIG_GEMINI diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/boot/vreset.c linux.ac/arch/ppc/boot/vreset.c --- linux-2.4.0/arch/ppc/boot/vreset.c Thu May 21 22:24:05 1998 +++ linux.ac/arch/ppc/boot/vreset.c Fri Dec 22 16:33:12 2000 @@ -19,12 +19,16 @@ */ #include "iso_font.h" -#include extern char *vidmem; extern int lines, cols; -/* estimate for delay */ -unsigned long loops_per_sec = 50000000;; + +static void mdelay(int ms) +{ + for (; ms > 0; --ms) + udelay(1000); +} + /* * VGA Register */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/chrpboot/Makefile linux.ac/arch/ppc/chrpboot/Makefile --- linux-2.4.0/arch/ppc/chrpboot/Makefile Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/chrpboot/Makefile Wed Jan 3 17:08:29 2001 @@ -23,11 +23,6 @@ OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o LIBS = $(TOPDIR)/lib/lib.a -ifeq ($(CONFIG_ALL_PPC),y) -# yes, we want to build chrp stuff -CONFIG_CHRP = y -endif - ifeq ($(CONFIG_SMP),y) TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE) else @@ -37,10 +32,10 @@ all: $(TOPDIR)/zImage # -# Only build anything here if we're configured for CHRP +# Only build anything here if we're configured for ALL_PPC # -- cort # -ifeq ($(CONFIG_CHRP),y) +ifeq ($(CONFIG_ALL_PPC),y) znetboot: zImage cp zImage $(TFTPIMAGE) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/coffboot/Makefile linux.ac/arch/ppc/coffboot/Makefile --- linux-2.4.0/arch/ppc/coffboot/Makefile Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/coffboot/Makefile Wed Jan 3 17:08:29 2001 @@ -20,18 +20,13 @@ MSIZE= endif -ifeq ($(CONFIG_ALL_PPC),y) -# yes, we want to build pmac stuff -CONFIG_PMAC = y -endif - ifeq ($(CONFIG_SMP),y) TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE) else TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE) endif -ifeq ($(CONFIG_PMAC),y) +ifeq ($(CONFIG_ALL_PPC),y) chrpmain.o: chrpmain.c $(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/coffboot/coffmain.c linux.ac/arch/ppc/coffboot/coffmain.c --- linux-2.4.0/arch/ppc/coffboot/coffmain.c Sat Jan 8 20:59:39 2000 +++ linux.ac/arch/ppc/coffboot/coffmain.c Mon Dec 18 20:41:38 2000 @@ -22,11 +22,18 @@ #define get_32be(x) (*(unsigned *)(x)) #define RAM_START 0xc0000000 -#define PROG_START RAM_START #define RAM_END (RAM_START + 0x800000) /* only 8M mapped with BATs */ +#define PROG_START RAM_START +#define PROG_SIZE 0x00400000 + +#define SCRATCH_SIZE (128 << 10) + char *avail_ram; -char *end_avail; +char *begin_avail, *end_avail; +char *avail_high; +unsigned int heap_use; +unsigned int heap_max; extern char _start[], _end[]; extern char image_data[]; @@ -34,6 +41,7 @@ extern char initrd_data[]; extern int initrd_len; +char heap[SCRATCH_SIZE]; boot(int a1, int a2, void *prom) { @@ -58,16 +66,18 @@ im = image_data; len = image_len; /* claim 3MB starting at 0 */ - claim(0, 3 << 20, 0); + claim(0, PROG_SIZE, 0); dst = (void *) RAM_START; if (im[0] == 0x1f && im[1] == 0x8b) { - /* claim 512kB for scratch space */ - avail_ram = claim(0, 512 << 10, 0x10) + RAM_START; - end_avail = avail_ram + (512 << 10); - printf("avail_ram = %x\n", avail_ram); + /* claim some memory for scratch space */ + begin_avail = avail_high = avail_ram = heap; + end_avail = heap + sizeof(heap); + printf("heap at 0x%x\n", avail_ram); printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); - gunzip(dst, 3 << 20, im, &len); + gunzip(dst, PROG_SIZE, im, &len); printf("done %u bytes\n", len); + printf("%u bytes of heap consumed, max in use %u\n", + avail_high - begin_avail, heap_max); } else { memmove(dst, im, len); } @@ -78,9 +88,6 @@ sa = (unsigned long)PROG_START; printf("start address = 0x%x\n", sa); -#if 0 - pause(); -#endif (*(void (*)())sa)(a1, a2, prom); printf("returned?\n"); @@ -114,13 +121,33 @@ rec = (struct bi_record *)((unsigned long)rec + rec->size); } +struct memchunk { + unsigned int size; + struct memchunk *next; +}; + +static struct memchunk *freechunks; + void *zalloc(void *x, unsigned items, unsigned size) { - void *p = avail_ram; + void *p; + struct memchunk **mpp, *mp; size *= items; size = (size + 7) & -8; + heap_use += size; + if (heap_use > heap_max) + heap_max = heap_use; + for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { + if (mp->size == size) { + *mpp = mp->next; + return mp; + } + } + p = avail_ram; avail_ram += size; + if (avail_ram > avail_high) + avail_high = avail_ram; if (avail_ram > end_avail) { printf("oops... out of memory\n"); pause(); @@ -130,6 +157,17 @@ void zfree(void *x, void *addr, unsigned nb) { + struct memchunk *mp = addr; + + nb = (nb + 7) & -8; + heap_use -= nb; + if (avail_ram == addr + nb) { + avail_ram = addr; + return; + } + mp->size = nb; + mp->next = freechunks; + freechunks = mp; } #define HEAD_CRC 2 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/config.in linux.ac/arch/ppc/config.in --- linux-2.4.0/arch/ppc/config.in Thu Nov 16 20:51:28 2000 +++ linux.ac/arch/ppc/config.in Wed Jan 3 17:08:29 2001 @@ -24,7 +24,7 @@ comment 'Platform support' define_bool CONFIG_PPC y choice 'Processor Type' \ - "6xx/7xx/7400 CONFIG_6xx \ + "6xx/7xx/74xx CONFIG_6xx \ 4xx CONFIG_4xx \ POWER3 CONFIG_POWER3 \ POWER4 CONFIG_POWER4 \ @@ -35,10 +35,11 @@ define_bool CONFIG_PPC64BRIDGE y define_bool CONFIG_ALL_PPC y fi - + if [ "$CONFIG_8260" = "y" ]; then define_bool CONFIG_6xx y define_bool CONFIG_SERIAL_CONSOLE y + bool 'Support for EST8260' CONFIG_EST8260 fi if [ "$CONFIG_4xx" = "y" ]; then @@ -59,25 +60,29 @@ TQM860 CONFIG_TQM860 \ MBX CONFIG_MBX \ WinCept CONFIG_WINCEPT" RPX-Lite + + if [ "$CONFIG_TQM_8xxL" = "y" ]; then + bool 'FPS850 Mainboard' CONFIG_FPS850 + fi fi -if [ "$CONFIG_6xx" = "y" ]; then + +if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then choice 'Machine Type' \ "PowerMac/PReP/MTX/CHRP CONFIG_ALL_PPC \ Gemini CONFIG_GEMINI \ - EST8260 CONFIG_EST8260 \ APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP fi -if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then - define_bool CONFIG_ALL_PPC n +if [ "$CONFIG_PPC64BRIDGE" != "y" ]; then + bool 'Workarounds for PPC601 bugs' CONFIG_PPC601_SYNC_FIX fi -if [ "$CONFIG_TQM8xxL" = "y" ]; then - bool 'FPS850 Mainboard' CONFIG_FPS850 +if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then + define_bool CONFIG_ALL_PPC n fi bool 'Symmetric multi-processing support' CONFIG_SMP -if [ "$CONFIG_6xx" = "y" ];then +if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then bool 'AltiVec Support' CONFIG_ALTIVEC fi @@ -106,14 +111,14 @@ if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \ "$CONFIG_8260" = "y" ]; then - define_bool CONFIG_PCI n + define_bool CONFIG_PCI n else - if [ "$CONFIG_8xx" = "y" ]; then - bool 'QSpan PCI' CONFIG_PCI_QSPAN - define_bool CONFIG_PCI $CONFIG_PCI_QSPAN - else - define_bool CONFIG_PCI y - fi + if [ "$CONFIG_8xx" = "y" ]; then + bool 'QSpan PCI' CONFIG_PCI_QSPAN + define_bool CONFIG_PCI $CONFIG_PCI_QSPAN + else + define_bool CONFIG_PCI y + fi fi bool 'Networking support' CONFIG_NET @@ -123,40 +128,34 @@ # only elf supported, a.out is not -- Cort if [ "$CONFIG_PROC_FS" = "y" ]; then - define_bool CONFIG_KCORE_ELF y + define_bool CONFIG_KCORE_ELF y fi define_bool CONFIG_BINFMT_ELF y define_bool CONFIG_KERNEL_ELF y tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC source drivers/pci/Config.in -source drivers/zorro/Config.in bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG if [ "$CONFIG_HOTPLUG" = "y" ]; then - source drivers/pcmcia/Config.in + source drivers/pcmcia/Config.in else - define_bool CONFIG_PCMCIA n + define_bool CONFIG_PCMCIA n fi source drivers/parport/Config.in if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then - bool 'Support for VGA Console' CONFIG_VGA_CONSOLE - bool 'Support for frame buffer devices' CONFIG_FB - if [ "$CONFIG_FB" = "y" ]; then - bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC - fi - tristate 'Support for /dev/rtc' CONFIG_PPC_RTC - bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE - bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT - bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP fi -if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then - bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL +if [ "$CONFIG_ALL_PPC" = "y" ]; then + bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE + bool 'Support for RTAS (RunTime Abstraction Services) in /proc' CONFIG_PPC_RTAS + bool 'Support for early boot text console (BootX or OpenFirmware only)' CONFIG_BOOTX_TEXT + bool 'Support for PReP Residual Data' CONFIG_PREP_RESIDUAL + bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then string 'Initial kernel command string' CONFIG_CMDLINE "console=ttyS0,9600 console=tty0 root=/dev/sda2" fi @@ -181,6 +180,7 @@ fi bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT bool '/proc/hardware support' CONFIG_PROC_HARDWARE + source drivers/zorro/Config.in fi endmenu @@ -254,7 +254,13 @@ mainmenu_option next_comment comment 'Console drivers' -source drivers/video/Config.in +if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then + bool 'Support for VGA Console' CONFIG_VGA_CONSOLE +fi + source drivers/video/Config.in +if [ "$CONFIG_FB" = "y" -a "$CONFIG_ALL_PPC" = "y" ]; then + bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC +fi endmenu source drivers/input/Config.in @@ -267,29 +273,27 @@ bool 'Support for CUDA based PowerMacs' CONFIG_ADB_CUDA bool 'Support for PMU based PowerMacs' CONFIG_ADB_PMU if [ "$CONFIG_ADB_PMU" = "y" ]; then - bool ' Power management support for PowerBooks' CONFIG_PMAC_PBOOK - # made a separate option since backlight may end up beeing used - # on non-powerbook machines (but only on PMU based ones AFAIK) - bool ' Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT + bool ' Power management support for PowerBooks' CONFIG_PMAC_PBOOK + # made a separate option since backlight may end up beeing used + # on non-powerbook machines (but only on PMU based ones AFAIK) + bool ' Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT fi bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL if [ "$CONFIG_MAC_SERIAL" = "y" ]; then - bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE + bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE fi bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB if [ "$CONFIG_ADB" = "y" ]; then - bool ' Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO - fi -fi -if [ "$CONFIG_ADB" = "y" ]; then - dep_bool ' Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT - if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then - define_bool CONFIG_MAC_HID y - bool ' Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES - bool ' Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN - else - bool ' Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD + bool ' Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO + dep_bool ' Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT + if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then + define_bool CONFIG_MAC_HID y + bool ' Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES + bool ' Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN + else + bool ' Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD + fi fi fi endmenu diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/apus_defconfig linux.ac/arch/ppc/configs/apus_defconfig --- linux-2.4.0/arch/ppc/configs/apus_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/apus_defconfig Wed Jan 3 17:08:29 2001 @@ -11,9 +11,7 @@ # # Loadable module support # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_MODULES is not set # # Platform support @@ -25,12 +23,13 @@ # CONFIG_POWER4 is not set # CONFIG_8260 is not set # CONFIG_8xx is not set -CONFIG_ALL_PPC=y +# CONFIG_ALL_PPC is not set # CONFIG_GEMINI is not set -# CONFIG_EST8260 is not set -# CONFIG_APUS is not set +CONFIG_APUS=y +CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set # CONFIG_ALTIVEC is not set +CONFIG_MACH_SPECIFIC=y # # General setup @@ -38,8 +37,10 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set -CONFIG_PCI=y +# CONFIG_MCA is not set +# CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y @@ -47,23 +48,35 @@ CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y -CONFIG_BINFMT_MISC=m -# CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# # CONFIG_PCMCIA is not set # # Parallel port support # # CONFIG_PARPORT is not set -# CONFIG_VGA_CONSOLE is not set +CONFIG_PPC_RTC=y +CONFIG_FB_CONSOLE=y +CONFIG_AMIGA=y +CONFIG_ZORRO=y +CONFIG_AMIGAMOUSE=y +CONFIG_ABSTRACT_CONSOLE=y CONFIG_FB=y -CONFIG_FB_COMPAT_XPMAC=y -# CONFIG_PPC_RTC is not set -CONFIG_PROC_DEVICETREE=y -# CONFIG_BOOTX_TEXT is not set -# CONFIG_MOTOROLA_HOTSWAP is not set -# CONFIG_CMDLINE_BOOL is not set +CONFIG_AMIGA_BUILTIN_SERIAL=y +# CONFIG_M68K_PRINTER is not set +CONFIG_GVPIOEXT=y +# CONFIG_GVPIOEXT_LP is not set +CONFIG_GVPIOEXT_PLIP=y +CONFIG_MULTIFACE_III_TTY=y +# CONFIG_SERIAL_CONSOLE is not set +CONFIG_HEARTBEAT=y +CONFIG_PROC_HARDWARE=y +CONFIG_ZORRO_NAMES=y # # Memory Technology Devices (MTD) @@ -80,12 +93,14 @@ # Block devices # # CONFIG_BLK_DEV_FD is not set +CONFIG_AMIGA_FLOPPY=y +CONFIG_AMIGA_Z2RAM=y # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 @@ -106,21 +121,17 @@ # # Networking options # -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK=y -# CONFIG_RTNETLINK is not set -# CONFIG_NETLINK_DEV is not set +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -CONFIG_IP_MULTICAST=y +# CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_IPV6 is not set @@ -131,7 +142,7 @@ # # # CONFIG_IPX is not set -CONFIG_ATALK=m +# CONFIG_ATALK is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set @@ -151,9 +162,48 @@ # # ATA/IDE/MFM/RLL support # -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +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_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +# CONFIG_BLK_DEV_IDECS is not set +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 + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_GAYLE=y +CONFIG_BLK_DEV_IDEDOUBLER=y +CONFIG_BLK_DEV_BUDDHA=y +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # # SCSI support @@ -165,7 +215,7 @@ # CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_ST is not set CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_SR_EXTRA_DEVS=2 @@ -176,29 +226,23 @@ # # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # # SCSI low-level drivers # -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AIC7XXX=y -# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set -CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 -CONFIG_AIC7XXX_PROC_STATS=y -CONFIG_AIC7XXX_RESET_DELAY=15 +# 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_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set @@ -211,30 +255,18 @@ # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_DEBUG is not set -CONFIG_SCSI_MESH=y -CONFIG_SCSI_MESH_SYNC_RATE=5 -CONFIG_SCSI_MAC53C94=y - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set +# CONFIG_SCSI_MESH is not set +# CONFIG_SCSI_MAC53C94 is not set # # Network device support @@ -245,34 +277,31 @@ # ARCnet devices # # CONFIG_ARCNET is not set - -# -# Appletalk devices -# -# CONFIG_APPLETALK is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MACE=y -CONFIG_BMAC=y +# CONFIG_MACE is not set +# CONFIG_BMAC is not set # CONFIG_GMAC is not set # CONFIG_NCR885E is not set # CONFIG_OAKNET is not set +CONFIG_ARIADNE=y +CONFIG_ARIADNE2=y +CONFIG_A2065=y +CONFIG_HYDRA=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -287,13 +316,16 @@ # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_BSDCOMP=y # CONFIG_PPPOE is not set -# CONFIG_SLIP is not set +CONFIG_SLIP=y +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set # # Wireless LAN (non-hamradio) @@ -336,44 +368,47 @@ # # Console drivers # +# CONFIG_VGA_CONSOLE is not set # # Frame-buffer support # CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set +CONFIG_FB_CLGEN=y +CONFIG_FB_PM2=y +CONFIG_FB_PM2_CVPPC=y # CONFIG_FB_CYBER2000 is not set -CONFIG_FB_OF=y -CONFIG_FB_CONTROL=y -CONFIG_FB_PLATINUM=y -CONFIG_FB_VALKYRIE=y -CONFIG_FB_CT65550=y -CONFIG_FB_IMSTT=y +CONFIG_FB_AMIGA=y +CONFIG_FB_AMIGA_OCS=y +CONFIG_FB_AMIGA_ECS=y +CONFIG_FB_AMIGA_AGA=y +CONFIG_FB_CYBER=y +CONFIG_FB_VIRGE=y +CONFIG_FB_RETINAZ3=y +# CONFIG_FB_FM2 is not set +# CONFIG_FB_OF is not set +# CONFIG_FB_CONTROL is not set +# CONFIG_FB_PLATINUM is not set +# CONFIG_FB_VALKYRIE is not set +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_IMSTT is not set # CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set -# CONFIG_FB_MATROX is not set -CONFIG_FB_ATY=y -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_SIS is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=y CONFIG_FBCON_CFB8=y CONFIG_FBCON_CFB16=y CONFIG_FBCON_CFB24=y CONFIG_FBCON_CFB32=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set +CONFIG_FBCON_AFB=y +CONFIG_FBCON_ILBM=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y -CONFIG_FONT_SUN8x16=y -CONFIG_FONT_SUN12x22=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set +CONFIG_FONT_PEARL_8x8=y # # Input core support @@ -383,23 +418,17 @@ # # Macintosh device drivers # -# CONFIG_ADB_CUDA is not set -# CONFIG_ADB_PMU is not set -CONFIG_MAC_FLOPPY=y -CONFIG_MAC_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -# CONFIG_ADB is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=m +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_UNIX98_PTYS is not set # # I2C support @@ -427,7 +456,7 @@ # # CONFIG_WATCHDOG is not set # CONFIG_INTEL_RNG is not set -CONFIG_NVRAM=y +# CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -449,24 +478,24 @@ # File systems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set +CONFIG_AFFS_FS=y CONFIG_HFS_FS=y # CONFIG_BFS_FS is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y # CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=m +CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set +CONFIG_MINIX_FS=y # CONFIG_NTFS_FS is not set # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set @@ -474,7 +503,7 @@ # CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set @@ -493,7 +522,7 @@ CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set -CONFIG_NFSD=y +# CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y @@ -505,8 +534,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set @@ -514,14 +541,14 @@ # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y +CONFIG_AMIGA_PARTITION=y CONFIG_NLS=y # # Native Language Support # CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -541,7 +568,7 @@ # CONFIG_NLS_CODEPAGE_936 is not set # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -558,23 +585,7 @@ # # Sound # -CONFIG_SOUND=y -# CONFIG_DMASOUND_AWACS is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_TVMIXER is not set +# CONFIG_SOUND is not set # # USB support diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/bseip_defconfig linux.ac/arch/ppc/configs/bseip_defconfig --- linux-2.4.0/arch/ppc/configs/bseip_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/bseip_defconfig Wed Jan 3 17:08:29 2001 @@ -32,6 +32,7 @@ # CONFIG_TQM860 is not set # CONFIG_MBX is not set # CONFIG_WINCEPT is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_ALL_PPC is not set # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y @@ -43,7 +44,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y @@ -190,7 +193,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -377,8 +379,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/common_defconfig linux.ac/arch/ppc/configs/common_defconfig --- linux-2.4.0/arch/ppc/configs/common_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/common_defconfig Wed Jan 3 17:08:29 2001 @@ -27,8 +27,8 @@ # CONFIG_8xx is not set CONFIG_ALL_PPC=y # CONFIG_GEMINI is not set -# CONFIG_EST8260 is not set # CONFIG_APUS is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_ALTIVEC=y @@ -38,7 +38,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_PCI=y CONFIG_NET=y CONFIG_SYSCTL=y @@ -48,7 +50,7 @@ CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_PCI_NAMES=y +# CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set @@ -56,13 +58,11 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_VGA_CONSOLE=y -CONFIG_FB=y -CONFIG_FB_COMPAT_XPMAC=y CONFIG_PPC_RTC=y CONFIG_PROC_DEVICETREE=y -CONFIG_BOOTX_TEXT=y -# CONFIG_MOTOROLA_HOTSWAP is not set +CONFIG_PPC_RTAS=y +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PREP_RESIDUAL is not set # CONFIG_CMDLINE_BOOL is not set # @@ -111,7 +111,8 @@ CONFIG_NETLINK=y # CONFIG_RTNETLINK is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -123,6 +124,34 @@ # CONFIG_IP_MROUTE is not set # CONFIG_INET_ECN is not set CONFIG_SYN_COOKIES=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_UNCLEAN=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_MIRROR=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_TARGET_LOG is not set +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_NAT_NEEDED=y +# CONFIG_IP_NF_COMPAT_IPFWADM is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -357,27 +386,28 @@ CONFIG_NET_PCI=y CONFIG_PCNET32=y # CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set -CONFIG_DE4X5=y # CONFIG_TULIP is not set +CONFIG_DE4X5=y # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PM is not set # CONFIG_LNE390 is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set # CONFIG_NE3210 is not set # CONFIG_ES3210 is not set -# CONFIG_RTL8129 is not set # CONFIG_8139TOO is not set +# CONFIG_RTL8129 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_WINBOND_840 is not set +# CONFIG_HAPPYMEAL is not set # CONFIG_NET_POCKET is not set # @@ -439,6 +469,7 @@ # # Console drivers # +CONFIG_VGA_CONSOLE=y # # Frame-buffer support @@ -458,9 +489,10 @@ # CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set CONFIG_FB_MATROX=y -CONFIG_FB_MATROX_MILLENIUM=y +# CONFIG_FB_MATROX_MILLENIUM is not set CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G100=y +# CONFIG_FB_MATROX_G100 is not set +# CONFIG_FB_MATROX_G450 is not set # CONFIG_FB_MATROX_MULTIHEAD is not set CONFIG_FB_ATY=y CONFIG_FB_ATY128=y @@ -481,6 +513,7 @@ # CONFIG_FONT_6x11 is not set # CONFIG_FONT_PEARL_8x8 is not set # CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FB_COMPAT_XPMAC is not set # # Input core support @@ -498,11 +531,10 @@ # CONFIG_ADB_CUDA=y CONFIG_ADB_PMU=y -CONFIG_PMAC_PBOOK=y -CONFIG_PMAC_BACKLIGHT=y -CONFIG_MAC_FLOPPY=y -CONFIG_MAC_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_PMAC_PBOOK is not set +# CONFIG_PMAC_BACKLIGHT is not set +# CONFIG_MAC_FLOPPY is not set +CONFIG_MAC_SERIAL=m CONFIG_ADB=y CONFIG_ADB_MACIO=y CONFIG_INPUT_ADBHID=y @@ -575,17 +607,17 @@ # File systems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y +CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set @@ -616,13 +648,13 @@ # Network File Systems # # CONFIG_CODA_FS is not set -CONFIG_NFS_FS=y +# CONFIG_NFS_FS is not set # CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set -CONFIG_NFSD=y +# CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -631,8 +663,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set @@ -695,64 +725,18 @@ # # Sound # -CONFIG_SOUND=y -CONFIG_DMASOUND_AWACS=y -CONFIG_DMASOUND=y -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -CONFIG_SOUND_OSS=y -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -CONFIG_SOUND_CS4232=m -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMPCI is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set +# CONFIG_SOUND is not set # # USB support # CONFIG_USB=y -CONFIG_USB_DEBUG=y +# CONFIG_USB_DEBUG is not set # # Miscellaneous USB options # -CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICEFS is not set # CONFIG_USB_BANDWIDTH is not set # @@ -763,33 +747,57 @@ CONFIG_USB_OHCI=y # -# USB Devices +# USB Device Class drivers # +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +# CONFIG_USB_WACOM is not set + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_SERIAL is not set + +# +# USB Multimedia devices +# # CONFIG_USB_IBMCAM is not set # CONFIG_USB_OV511 is not set -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_USS720 is not set +# CONFIG_USB_DSBR is not set # CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_BLUETOOTH is not set # CONFIG_USB_NET1080 is not set # -# USB Human Interface Devices (HID) +# USB port drivers # -CONFIG_USB_HID=y -# CONFIG_USB_WACOM is not set +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB misc drivers +# +# CONFIG_USB_RIO500 is not set # # Kernel hacking diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/est8260_defconfig linux.ac/arch/ppc/configs/est8260_defconfig --- linux-2.4.0/arch/ppc/configs/est8260_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/est8260_defconfig Wed Jan 3 17:08:29 2001 @@ -25,13 +25,10 @@ # CONFIG_8xx is not set CONFIG_6xx=y CONFIG_SERIAL_CONSOLE=y -# CONFIG_ALL_PPC is not set -# CONFIG_GEMINI is not set CONFIG_EST8260=y -# CONFIG_APUS is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_ALL_PPC is not set # CONFIG_SMP is not set -# CONFIG_ALTIVEC is not set CONFIG_MACH_SPECIFIC=y # @@ -40,7 +37,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y @@ -57,12 +56,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set # CONFIG_PPC_RTC is not set -# CONFIG_PROC_DEVICETREE is not set -# CONFIG_BOOTX_TEXT is not set -# CONFIG_MOTOROLA_HOTSWAP is not set # # Memory Technology Devices (MTD) @@ -192,7 +186,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -250,6 +243,7 @@ # # Console drivers # +# CONFIG_VGA_CONSOLE is not set # # Frame-buffer support @@ -379,8 +373,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/gemini_defconfig linux.ac/arch/ppc/configs/gemini_defconfig --- linux-2.4.0/arch/ppc/configs/gemini_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/gemini_defconfig Wed Jan 3 17:08:29 2001 @@ -12,7 +12,7 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y CONFIG_KMOD=y # @@ -27,8 +27,8 @@ # CONFIG_8xx is not set # CONFIG_ALL_PPC is not set CONFIG_GEMINI=y -# CONFIG_EST8260 is not set # CONFIG_APUS is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_ALTIVEC=y CONFIG_MACH_SPECIFIC=y @@ -39,7 +39,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_PCI=y CONFIG_NET=y CONFIG_SYSCTL=y @@ -57,12 +59,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set # CONFIG_PPC_RTC is not set -# CONFIG_PROC_DEVICETREE is not set -# CONFIG_BOOTX_TEXT is not set -# CONFIG_MOTOROLA_HOTSWAP is not set # # Memory Technology Devices (MTD) @@ -324,6 +321,7 @@ # # Console drivers # +# CONFIG_VGA_CONSOLE is not set # # Frame-buffer support @@ -454,8 +452,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/mbx_defconfig linux.ac/arch/ppc/configs/mbx_defconfig --- linux-2.4.0/arch/ppc/configs/mbx_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/mbx_defconfig Wed Jan 3 17:08:29 2001 @@ -32,6 +32,7 @@ # CONFIG_TQM860 is not set CONFIG_MBX=y # CONFIG_WINCEPT is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_ALL_PPC is not set # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y @@ -43,7 +44,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y @@ -184,7 +187,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -370,8 +372,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/oak_defconfig linux.ac/arch/ppc/configs/oak_defconfig --- linux-2.4.0/arch/ppc/configs/oak_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/oak_defconfig Wed Jan 3 17:08:29 2001 @@ -12,7 +12,7 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y CONFIG_KMOD=y # @@ -27,6 +27,7 @@ # CONFIG_8xx is not set CONFIG_OAK=y # CONFIG_WALNUT is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # CONFIG_MATH_EMULATION is not set @@ -37,7 +38,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y @@ -179,7 +182,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -366,8 +368,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/rpxcllf_defconfig linux.ac/arch/ppc/configs/rpxcllf_defconfig --- linux-2.4.0/arch/ppc/configs/rpxcllf_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/rpxcllf_defconfig Wed Jan 3 17:08:29 2001 @@ -32,6 +32,7 @@ # CONFIG_TQM860 is not set # CONFIG_MBX is not set # CONFIG_WINCEPT is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_ALL_PPC is not set # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y @@ -43,7 +44,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y @@ -190,7 +193,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -377,8 +379,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/rpxlite_defconfig linux.ac/arch/ppc/configs/rpxlite_defconfig --- linux-2.4.0/arch/ppc/configs/rpxlite_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/rpxlite_defconfig Wed Jan 3 17:08:29 2001 @@ -32,6 +32,7 @@ # CONFIG_TQM860 is not set # CONFIG_MBX is not set # CONFIG_WINCEPT is not set +CONFIG_PPC601_SYNC_FIX=y # CONFIG_ALL_PPC is not set # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y @@ -43,7 +44,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y @@ -190,7 +193,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -377,8 +379,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/configs/walnut_defconfig linux.ac/arch/ppc/configs/walnut_defconfig --- linux-2.4.0/arch/ppc/configs/walnut_defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/configs/walnut_defconfig Wed Jan 3 17:08:29 2001 @@ -12,7 +12,7 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y CONFIG_KMOD=y # @@ -27,6 +27,7 @@ # CONFIG_8xx is not set # CONFIG_OAK is not set CONFIG_WALNUT=y +CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # CONFIG_MATH_EMULATION is not set @@ -37,7 +38,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y @@ -179,7 +182,6 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set -# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -369,8 +371,6 @@ # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set # CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/defconfig linux.ac/arch/ppc/defconfig --- linux-2.4.0/arch/ppc/defconfig Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/defconfig Mon Dec 18 20:42:03 2000 @@ -12,7 +12,7 @@ # Loadable module support # CONFIG_MODULES=y -CONFIG_MODVERSIONS=y +# CONFIG_MODVERSIONS is not set CONFIG_KMOD=y # @@ -38,7 +38,9 @@ # CONFIG_HIGHMEM is not set # CONFIG_MOL is not set # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_PCI=y CONFIG_NET=y CONFIG_SYSCTL=y @@ -48,7 +50,7 @@ CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_PCI_NAMES=y +# CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set @@ -58,11 +60,13 @@ # CONFIG_PARPORT is not set CONFIG_VGA_CONSOLE=y CONFIG_FB=y -CONFIG_FB_COMPAT_XPMAC=y +# CONFIG_FB_COMPAT_XPMAC is not set CONFIG_PPC_RTC=y CONFIG_PROC_DEVICETREE=y -CONFIG_BOOTX_TEXT=y +CONFIG_PPC_RTAS=y +# CONFIG_BOOTX_TEXT is not set # CONFIG_MOTOROLA_HOTSWAP is not set +# CONFIG_PREP_RESIDUAL is not set # CONFIG_CMDLINE_BOOL is not set # @@ -74,14 +78,11 @@ # Plug and Play configuration # # CONFIG_PNP is not set -# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -95,13 +96,6 @@ # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -111,7 +105,8 @@ CONFIG_NETLINK=y # CONFIG_RTNETLINK is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -123,6 +118,34 @@ # CONFIG_IP_MROUTE is not set # CONFIG_INET_ECN is not set CONFIG_SYN_COOKIES=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_UNCLEAN=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_MIRROR=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_TARGET_LOG is not set +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_NAT_NEEDED=y +# CONFIG_IP_NF_COMPAT_IPFWADM is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -166,15 +189,7 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set # CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set # CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -# CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y @@ -184,8 +199,6 @@ # IDE chipset support/bugfixes # # CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y @@ -194,24 +207,17 @@ CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set # CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set @@ -347,37 +353,31 @@ # CONFIG_NCR885E is not set # CONFIG_OAKNET is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set CONFIG_NET_PCI=y CONFIG_PCNET32=y # CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set # CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -CONFIG_DE4X5=y # CONFIG_TULIP is not set +CONFIG_DE4X5=y # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set -# CONFIG_LNE390 is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_RTL8129 is not set # CONFIG_8139TOO is not set +# CONFIG_RTL8129 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_WINBOND_840 is not set +# CONFIG_HAPPYMEAL is not set # CONFIG_NET_POCKET is not set # @@ -458,9 +458,9 @@ # CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set CONFIG_FB_MATROX=y -CONFIG_FB_MATROX_MILLENIUM=y +# CONFIG_FB_MATROX_MILLENIUM is not set CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G100=y +# CONFIG_FB_MATROX_G100 is not set # CONFIG_FB_MATROX_MULTIHEAD is not set CONFIG_FB_ATY=y CONFIG_FB_ATY128=y @@ -498,11 +498,10 @@ # CONFIG_ADB_CUDA=y CONFIG_ADB_PMU=y -CONFIG_PMAC_PBOOK=y -CONFIG_PMAC_BACKLIGHT=y -CONFIG_MAC_FLOPPY=y -CONFIG_MAC_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_PMAC_PBOOK is not set +# CONFIG_PMAC_BACKLIGHT is not set +# CONFIG_MAC_FLOPPY is not set +CONFIG_MAC_SERIAL=m CONFIG_ADB=y CONFIG_ADB_MACIO=y CONFIG_INPUT_ADBHID=y @@ -575,26 +574,24 @@ # File systems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y +CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set +CONFIG_JFFS_FS_VERBOSE=0 # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y CONFIG_DEVFS_FS=y @@ -602,39 +599,22 @@ # CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -695,64 +675,18 @@ # # Sound # -CONFIG_SOUND=y -CONFIG_DMASOUND_AWACS=y -CONFIG_DMASOUND=y -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -CONFIG_SOUND_OSS=y -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -CONFIG_SOUND_CS4232=m -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_YMPCI is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set +# CONFIG_SOUND is not set # # USB support # CONFIG_USB=y -CONFIG_USB_DEBUG=y +# CONFIG_USB_DEBUG is not set # # Miscellaneous USB options # -CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICEFS is not set # CONFIG_USB_BANDWIDTH is not set # @@ -768,20 +702,15 @@ # CONFIG_USB_PRINTER is not set # CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set -# CONFIG_USB_AUDIO is not set # CONFIG_USB_ACM is not set # CONFIG_USB_SERIAL is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_OV511 is not set # CONFIG_USB_DC2XX is not set # CONFIG_USB_MDC800 is not set # CONFIG_USB_STORAGE is not set -# CONFIG_USB_USS720 is not set # CONFIG_USB_DABUSB is not set # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RIO500 is not set -# CONFIG_USB_DSBR is not set # CONFIG_USB_BLUETOOTH is not set # CONFIG_USB_NET1080 is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/apus_setup.c linux.ac/arch/ppc/kernel/apus_setup.c --- linux-2.4.0/arch/ppc/kernel/apus_setup.c Sun Oct 8 17:33:07 2000 +++ linux.ac/arch/ppc/kernel/apus_setup.c Mon Dec 18 20:42:03 2000 @@ -647,25 +647,6 @@ return 0; } -int -apus_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return 0; -} - -void -apus_ide_request_region(ide_ioreg_t from, - unsigned int extent, - const char *name) -{ -} - -void -apus_ide_release_region(ide_ioreg_t from, - unsigned int extent) -{ -} - void apus_ide_fix_driveid(struct hd_driveid *id) { @@ -1131,9 +1112,6 @@ ppc_ide_md.outsw = apus_ide_outsw; ppc_ide_md.default_irq = apus_ide_default_irq; ppc_ide_md.default_io_base = apus_ide_default_io_base; - ppc_ide_md.ide_check_region = apus_ide_check_region; - ppc_ide_md.ide_request_region = apus_ide_request_region; - ppc_ide_md.ide_release_region = apus_ide_release_region; ppc_ide_md.fix_driveid = apus_ide_fix_driveid; ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/chrp_pci.c linux.ac/arch/ppc/kernel/chrp_pci.c --- linux-2.4.0/arch/ppc/kernel/chrp_pci.c Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/kernel/chrp_pci.c Mon Dec 18 20:42:30 2000 @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include #include @@ -19,16 +19,19 @@ #include #include #include +#include +#include "open_pic.h" #include "pci.h" + #ifdef CONFIG_POWER4 -static unsigned long pci_address_offset(int, unsigned int); +extern unsigned long pci_address_offset(int, unsigned int); #endif /* CONFIG_POWER4 */ /* LongTrail */ -#define pci_config_addr(bus, dev, offset) \ -(GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset)) +#define pci_config_addr(dev, offset) \ +(GG2_PCI_CONFIG_BASE | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset)) volatile struct Hydra *Hydra = NULL; @@ -37,205 +40,127 @@ * limit the bus number to 3 bits */ -int __chrp gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - if (bus > 7) { - *val = 0xff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - *val = in_8((unsigned char *)pci_config_addr(bus, dev_fn, offset)); - return PCIBIOS_SUCCESSFUL; -} - -int __chrp gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - if (bus > 7) { - *val = 0xffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - *val = in_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset)); - return PCIBIOS_SUCCESSFUL; -} - +#define cfg_read(val, addr, type, op) *val = op((type)(addr)) +#define cfg_write(val, addr, type, op) op((type *)(addr), (val)) -int __chrp gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - if (bus > 7) { - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - *val = in_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset)); - return PCIBIOS_SUCCESSFUL; -} - -int __chrp gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - if (bus > 7) - return PCIBIOS_DEVICE_NOT_FOUND; - out_8((unsigned char *)pci_config_addr(bus, dev_fn, offset), val); - return PCIBIOS_SUCCESSFUL; -} - -int __chrp gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - if (bus > 7) - return PCIBIOS_DEVICE_NOT_FOUND; - out_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset), val); - return PCIBIOS_SUCCESSFUL; -} +#define cfg_read_bad(val, size) *val = bad_##size; +#define cfg_write_bad(val, size) -int __chrp gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - if (bus > 7) - return PCIBIOS_DEVICE_NOT_FOUND; - out_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset), val); - return PCIBIOS_SUCCESSFUL; -} +#define bad_byte 0xff +#define bad_word 0xffff +#define bad_dword 0xffffffffU + +#define GG2_PCI_OP(rw, size, type, op) \ +int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \ +{ \ + if (dev->bus->number > 7) { \ + cfg_##rw##_bad(val, size) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ + } \ + cfg_##rw(val, pci_config_addr(dev, off), type, op); \ + return PCIBIOS_SUCCESSFUL; \ +} + +GG2_PCI_OP(read, byte, u8 *, in_8) +GG2_PCI_OP(read, word, u16 *, in_le16) +GG2_PCI_OP(read, dword, u32 *, in_le32) +GG2_PCI_OP(write, byte, u8, out_8) +GG2_PCI_OP(write, word, u16, out_le16) +GG2_PCI_OP(write, dword, u32, out_le32) + +static struct pci_ops gg2_pci_ops = +{ + gg2_read_config_byte, + gg2_read_config_word, + gg2_read_config_dword, + gg2_write_config_byte, + gg2_write_config_word, + gg2_write_config_dword +}; -#define python_config_address(bus) (unsigned *)((0xfef00000+0xf8000)-(bus*0x100000)) -#define python_config_data(bus) ((0xfef00000+0xf8010)-(bus*0x100000)) -#define PYTHON_CFA(b, d, o) (0x80 | ((b<<6) << 8) | ((d) << 16) \ +/* + * Access functions for PCI config space on IBM "python" host bridges. + */ +#define PYTHON_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ | (((o) & ~3) << 24)) -unsigned int python_busnr = 0; - -int __chrp python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - if (bus > python_busnr) { - *val = 0xff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset)); - *val = in_8((unsigned char *)python_config_data(bus) + (offset&3)); - return PCIBIOS_SUCCESSFUL; -} - -int __chrp python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - if (bus > python_busnr) { - *val = 0xffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset)); - *val = in_le16((unsigned short *)(python_config_data(bus) + (offset&3))); - return PCIBIOS_SUCCESSFUL; -} - - -int __chrp python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - if (bus > python_busnr) { - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset)); - *val = in_le32((unsigned *)python_config_data(bus)); - return PCIBIOS_SUCCESSFUL; -} -int __chrp python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - if (bus > python_busnr) - return PCIBIOS_DEVICE_NOT_FOUND; - out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset)); - out_8((volatile unsigned char *)python_config_data(bus) + (offset&3), val); - return PCIBIOS_SUCCESSFUL; -} - -int __chrp python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - if (bus > python_busnr) - return PCIBIOS_DEVICE_NOT_FOUND; - out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset)); - out_le16((volatile unsigned short *)python_config_data(bus) + (offset&3), - val); - return PCIBIOS_SUCCESSFUL; -} - -int __chrp python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - if (bus > python_busnr) - return PCIBIOS_DEVICE_NOT_FOUND; - out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset)); - out_le32((unsigned *)python_config_data(bus) + (offset&3), val); - return PCIBIOS_SUCCESSFUL; -} - - -int __chrp rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - unsigned long ret; - - if (call_rtas( "read-pci-config", 2, 2, &ret, addr, 1) != 0) - return PCIBIOS_DEVICE_NOT_FOUND; - *val = ret; - return PCIBIOS_SUCCESSFUL; -} - -int __chrp rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - unsigned long ret; - - if (call_rtas("read-pci-config", 2, 2, &ret, addr, 2) != 0) - return PCIBIOS_DEVICE_NOT_FOUND; - *val = ret; - return PCIBIOS_SUCCESSFUL; -} - - -int __chrp rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - unsigned long ret; - - if (call_rtas("read-pci-config", 2, 2, &ret, addr, 4) != 0) - return PCIBIOS_DEVICE_NOT_FOUND; - *val = ret; - return PCIBIOS_SUCCESSFUL; -} - -int __chrp rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 1, (ulong)val ) != 0 ) - return PCIBIOS_DEVICE_NOT_FOUND; - return PCIBIOS_SUCCESSFUL; -} - -int __chrp rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 2, (ulong)val ) != 0 ) - return PCIBIOS_DEVICE_NOT_FOUND; - return PCIBIOS_SUCCESSFUL; -} +#define PYTHON_PCI_OP(rw, size, type, op, mask) \ +int __chrp \ +python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + struct pci_controller *hose = dev->sysdata; \ + \ + out_be32(hose->cfg_addr, \ + PYTHON_CFA(dev->bus->number, dev->devfn, offset)); \ + cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ + return PCIBIOS_SUCCESSFUL; \ +} + +PYTHON_PCI_OP(read, byte, u8 *, in_8, 3) +PYTHON_PCI_OP(read, word, u16 *, in_le16, 2) +PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0) +PYTHON_PCI_OP(write, byte, u8, out_8, 3) +PYTHON_PCI_OP(write, word, u16, out_le16, 2) +PYTHON_PCI_OP(write, dword, u32, out_le32, 0) + +static struct pci_ops python_pci_ops = +{ + python_read_config_byte, + python_read_config_word, + python_read_config_dword, + python_write_config_byte, + python_write_config_word, + python_write_config_dword +}; -int __chrp rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - if ( call_rtas( "write-pci-config", 3, 1, NULL, addr, 4, (ulong)val ) != 0 ) - return PCIBIOS_DEVICE_NOT_FOUND; - return PCIBIOS_SUCCESSFUL; -} +#ifdef CONFIG_POWER4 +/* + * Access functions for PCI config space using RTAS calls. + */ +#define RTAS_PCI_READ_OP(size, type, nbytes) \ +int __chrp \ +rtas_read_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \ + | ((dev->bus->number & 0xff) << 16); \ + unsigned long ret = ~0UL; \ + int rval; \ + \ + rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes); \ + *val = ret; \ + return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \ +} + +#define RTAS_PCI_WRITE_OP(size, type, nbytes) \ +int __chrp \ +rtas_write_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \ + | ((dev->bus->number & 0xff) << 16); \ + int rval; \ + \ + rval = call_rtas("write-pci-config", 3, 1, NULL, \ + addr, nbytes, (ulong)val); \ + return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \ +} + +RTAS_PCI_READ_OP(byte, u8 *, 1) +RTAS_PCI_READ_OP(word, u16 *, 2) +RTAS_PCI_READ_OP(dword, u32 *, 4) +RTAS_PCI_WRITE_OP(byte, u8, 1) +RTAS_PCI_WRITE_OP(word, u16, 2) +RTAS_PCI_WRITE_OP(dword, u32, 4) + +static struct pci_ops rtas_pci_ops = +{ + rtas_read_config_byte, + rtas_read_config_word, + rtas_read_config_dword, + rtas_write_config_byte, + rtas_write_config_word, + rtas_write_config_dword +}; +#endif /* CONFIG_POWER4 */ /* * Temporary fixes for PCI devices. These should be replaced by OF query @@ -278,7 +203,7 @@ HYDRA_FC_MPIC_ENABLE | HYDRA_FC_SLOW_SCC_PCLK | HYDRA_FC_MPIC_IS_MASTER)); - OpenPIC = (volatile struct OpenPIC *)&Hydra->OpenPIC; + OpenPIC_Addr = &Hydra->OpenPIC; OpenPIC_InitSenses = hydra_openpic_initsenses; OpenPIC_NumInitSenses = sizeof(hydra_openpic_initsenses); return 1; @@ -316,54 +241,25 @@ chrp_pcibios_fixup(void) { struct pci_dev *dev; - int *brp; struct device_node *np; - extern struct pci_ops generic_pci_ops; - -#ifndef CONFIG_POWER4 - np = find_devices("device-tree"); - if (np != 0) { - for (np = np->child; np != NULL; np = np->sibling) { - if (np->type == NULL || strcmp(np->type, "pci") != 0) - continue; - if ((brp = (int *) get_property(np, "bus-range", NULL)) == 0) - continue; - if (brp[0] != 0) /* bus 0 is already done */ - pci_scan_bus(brp[0], &generic_pci_ops, NULL); - } - } -#else - /* XXX kludge for now because we can't properly handle - physical addresses > 4GB. -- paulus */ - pci_scan_bus(0x1e, &generic_pci_ops, NULL); -#endif /* CONFIG_POWER4 */ /* PCI interrupts are controlled by the OpenPIC */ pci_for_each_dev(dev) { - np = find_pci_device_OFnode(dev->bus->number, dev->devfn); + np = pci_device_to_OF_node(dev); if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0)) dev->irq = np->intrs[0].line; - /* these need to be absolute addrs for OF and Matrox FB -- Cort */ - if ( dev->vendor == PCI_VENDOR_ID_MATROX ) - { - if ( dev->resource[0].start < isa_mem_base ) - dev->resource[0].start += isa_mem_base; - if ( dev->resource[1].start < isa_mem_base ) - dev->resource[1].start += isa_mem_base; - } + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + /* the F50 identifies the amd as a trident */ if ( (dev->vendor == PCI_VENDOR_ID_TRIDENT) && (dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET) ) { dev->vendor = PCI_VENDOR_ID_AMD; - pcibios_write_config_word(dev->bus->number, - dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); + pci_write_config_word(dev, PCI_VENDOR_ID, + PCI_VENDOR_ID_AMD); } #ifdef CONFIG_POWER4 power4_fixup_dev(dev); -#else - if (dev->bus->number > 0 && python_busnr > 0) - dev->resource[0].start += dev->bus->number*0x01000000; #endif } } @@ -402,86 +298,213 @@ bus->resource[1] = &gg2_resources.pci_mem; } -decl_config_access_method(grackle); -decl_config_access_method(indirect); -decl_config_access_method(rtas); +static void process_bridge_ranges(struct pci_controller *hose, + struct device_node *dev, int index) +{ + unsigned int *ranges; + int rlen = 0; + int memno = 0; + struct resource *res; + + hose->io_base_phys = 0; + ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + while ((rlen -= 6 * sizeof(unsigned int)) >= 0) { + res = NULL; + switch (ranges[0] >> 24) { + case 1: /* I/O space */ + if (ranges[2] != 0) + break; + hose->io_base_phys = ranges[3]; + hose->io_base_virt = ioremap(ranges[3], ranges[5]); + if (index == 0) { + isa_io_base = (unsigned long) hose->io_base_virt; + printk("isa_io_base=%lx\n", isa_io_base); + } + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + break; + case 2: /* memory space */ + if (index == 0 && ranges[1] == 0 && ranges[2] == 0){ + isa_mem_base = ranges[3]; + printk("isa_mem_base=%lx\n", isa_mem_base); + } + if (memno == 0) { + hose->pci_mem_offset = ranges[3] - ranges[2]; + printk("pci_mem_offset=%lx for this bridge\n", + hose->pci_mem_offset); + } + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + ++memno; + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->start = ranges[3]; + res->end = res->start + ranges[5] - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += 6; + } +} + +/* this is largely modeled and stolen after the pmac_pci code -- tgall + */ + +static void __init +ibm_add_bridges(struct device_node *dev) +{ + int *bus_range; + int len, index = 0; + struct pci_controller *hose; + volatile unsigned char *cfg; + unsigned int *dma; +#ifdef CONFIG_POWER3 + unsigned long *opprop = (unsigned long *) + get_property(find_path_device("/"), "platform-open-pic", NULL); +#endif + + for(; dev != NULL; dev = dev->next, ++index) { + 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->type, + dev->addrs[0].address); + + hose = pcibios_alloc_controller(); + if (!hose) { + printk("Can't allocate PCI controller structure for %s\n", + dev->full_name); + continue; + } + hose->arch_data = dev; + hose->first_busno = bus_range[0]; + hose->last_busno = bus_range[1]; + hose->ops = &python_pci_ops; + + cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20); + hose->cfg_addr = (volatile unsigned int *) cfg; + hose->cfg_data = cfg + 0x10; + + process_bridge_ranges(hose, dev, index); + +#ifdef CONFIG_POWER3 + openpic_setup_ISU(index, opprop[index+1]); +#endif /* CONFIG_POWER3 */ + + /* check the first bridge for a property that we can + use to set pci_dram_offset */ + dma = (unsigned int *) + get_property(dev, "ibm,dma-ranges", &len); + if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) { + pci_dram_offset = dma[2] - dma[3]; + printk("pci_dram_offset = %lx\n", pci_dram_offset); + } + } +} +#ifdef CONFIG_POWER4 void __init -chrp_setup_pci_ptrs(void) +power4_add_bridge(void) +{ + struct pci_controller* hose; + + hose = pcibios_alloc_controller(); + if (!hose) + return; + hose->first_busno = 0; + hose->last_busno = 0xff; + + hose->ops = &rtas_pci_ops; + pci_dram_offset = 0; +} +#endif /* CONFIG_POWER4 */ + +void __init +chrp_find_bridges(void) { struct device_node *py; + char *model, *name; + struct pci_controller* hose; ppc_md.pcibios_fixup = chrp_pcibios_fixup; + #ifdef CONFIG_POWER4 - set_config_access_method(rtas); - pci_dram_offset = 0; + power4_add_bridge(); #else /* CONFIG_POWER4 */ - if ( !strncmp("MOT", - get_property(find_path_device("/"), "model", NULL),3) ) - { - pci_dram_offset = 0; - isa_mem_base = 0xf7000000; - isa_io_base = 0xfe000000; - set_config_access_method(grackle); + model = get_property(find_path_device("/"), "model", NULL); + if (!strncmp("MOT", model, 3)) { + struct pci_controller* hose; + + hose = pcibios_alloc_controller(); + if (!hose) + return; + hose->first_busno = 0; + hose->last_busno = 0xff; + /* Check that please. This must be the root of the OF + * PCI tree (the root host bridge + */ + hose->arch_data = find_devices("pci"); + setup_grackle(hose, 0x20000); + return; } - else - { - if ((py = find_compatible_devices("pci", "IBM,python")) != 0 - || (py = find_compatible_devices("pci", "IBM,python3.0")) != 0) - { - char *name = get_property(find_path_device("/"), "name", NULL); - /* find out how many pythons */ - while ( (py = py->next) ) python_busnr++; - set_config_access_method(python); - - /* - * We base these values on the machine type but should - * try to read them from the python controller itself. - * -- Cort - */ - if ( !strncmp("IBM,7025-F50", name, 12) ) - { - pci_dram_offset = 0x80000000; - isa_mem_base = 0xa0000000; - isa_io_base = 0x88000000; - } else if ( !strncmp("IBM,7043-260", name, 12) - || !strncmp("IBM,7044-270", name, 12)) - { - pci_dram_offset = 0x0; - isa_mem_base = 0xc0000000; - isa_io_base = 0xf8000000; - } - } - else - { - if ( !strncmp("IBM,7043-150", get_property(find_path_device("/"), "name", NULL),12) || - !strncmp("IBM,7046-155", get_property(find_path_device("/"), "name", NULL),12) || - !strncmp("IBM,7046-B50", get_property(find_path_device("/"), "name", NULL),12) ) - { - pci_dram_offset = 0; - isa_mem_base = 0x80000000; - isa_io_base = 0xfe000000; - pci_config_address = (unsigned int *)0xfec00000; - pci_config_data = (unsigned char *)0xfee00000; - set_config_access_method(indirect); - } - else - { - /* LongTrail */ - pci_dram_offset = 0; - isa_mem_base = 0xf7000000; - isa_io_base = 0xf8000000; - set_config_access_method(gg2); - ppc_md.pcibios_fixup = gg2_pcibios_fixup; - ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus; - } - } - } + if ((py = find_compatible_devices("pci", "IBM,python"))) + { + /* XXX xmon_init_scc needs this set and the BAT + set up in MMU_init */ + ibm_add_bridges(find_devices("pci")); + return; + } + + + hose = pcibios_alloc_controller(); + if (!hose) + return; + hose->first_busno = 0; + hose->last_busno = 0xff; + /* Check that please. This must be the root of the OF + * PCI tree (the root host bridge + */ + hose->arch_data = find_devices("pci"); + name = get_property(find_path_device("/"), "name", NULL); + if (!strncmp("IBM,7043-150", name, 12) || + !strncmp("IBM,7046-155", name, 12) || + !strncmp("IBM,7046-B50", name, 12) ) { + setup_grackle(hose, 0x01000000); + isa_mem_base = 0x80000000; + return; + } + + /* LongTrail */ + hose->ops = &gg2_pci_ops; + pci_dram_offset = 0; + isa_mem_base = 0xf7000000; + hose->io_base_phys = (unsigned long) 0xf8000000; + hose->io_base_virt = ioremap(hose->io_base_phys, 0x10000); + isa_io_base = (unsigned long) hose->io_base_virt; + ppc_md.pcibios_fixup = gg2_pcibios_fixup; + ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus; #endif /* CONFIG_POWER4 */ } #ifdef CONFIG_PPC64BRIDGE +#ifdef CONFIG_POWER4 /* * Hack alert!!! * 64-bit machines like POWER3 and POWER4 have > 32 bit @@ -490,9 +513,7 @@ * page table gives us into parts of the physical address * space above 4GB so we can access the I/O devices. */ - -#ifdef CONFIG_POWER4 -static unsigned long pci_address_offset(int busnr, unsigned int flags) +unsigned long pci_address_offset(int busnr, unsigned int flags) { unsigned long offset = 0; @@ -507,35 +528,6 @@ else } return offset; -} - -unsigned long phys_to_bus(unsigned long pa) -{ - if (pa >= 0xf8000000) - pa -= 0x38000000; - else if (pa >= 0x80000000 && pa < 0xc0000000) - pa += 0x40000000; - return pa; -} - -unsigned long bus_to_phys(unsigned int ba, int busnr) -{ - return ba + pci_address_offset(busnr, IORESOURCE_MEM); -} - -#else /* CONFIG_POWER4 */ -/* - * For now assume I/O addresses are < 4GB and PCI bridges don't - * remap addresses on POWER3 machines. - */ -unsigned long phys_to_bus(unsigned long pa) -{ - return pa; -} - -unsigned long bus_to_phys(unsigned int ba, int busnr) -{ - return ba; } #endif /* CONFIG_POWER4 */ #endif /* CONFIG_PPC64BRIDGE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/chrp_setup.c linux.ac/arch/ppc/kernel/chrp_setup.c --- linux-2.4.0/arch/ppc/kernel/chrp_setup.c Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/kernel/chrp_setup.c Fri Dec 22 16:33:56 2000 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -50,21 +49,19 @@ #include #include #include - #include + #include "local_irq.h" #include "i8259.h" #include "open_pic.h" #include "xics.h" -extern volatile unsigned char *chrp_int_ack_special; - unsigned long chrp_get_rtc_time(void); int chrp_set_rtc_time(unsigned long nowtime); void chrp_calibrate_decr(void); long chrp_time_init(void); -void chrp_setup_pci_ptrs(void); +void chrp_find_bridges(void); void chrp_event_scan(void); void rtas_display_progress(char *, unsigned short); void rtas_indicator_progress(char *, unsigned short); @@ -92,7 +89,7 @@ extern PTE *Hash, *Hash_end; extern unsigned long Hash_size, Hash_mask; extern int probingmem; -extern unsigned long loops_per_sec; +extern unsigned long loops_per_jiffy; extern int bootx_text_mapped; static int max_width; @@ -244,7 +241,7 @@ struct device_node *device; /* init to some ~sane value until calibrate_delay() runs */ - loops_per_sec = 50000000; + loops_per_jiffy = 50000000/HZ; #ifdef CONFIG_BLK_DEV_INITRD /* this is fine for chrp */ @@ -257,6 +254,9 @@ ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */ printk("Boot arguments: %s\n", cmd_line); + /* Lookup PCI host bridges */ + chrp_find_bridges(); + #ifndef CONFIG_PPC64BRIDGE /* PCI bridge config space access area - * appears to be not in devtree on longtrail. */ @@ -266,11 +266,12 @@ * -- Geert */ hydra_init(); /* Mac I/O */ + #endif /* CONFIG_PPC64BRIDGE */ #ifndef CONFIG_POWER4 /* Some IBM machines don't have the hydra -- Cort */ - if ( !OpenPIC ) + if ( !OpenPIC_Addr ) { unsigned long *opprop; @@ -279,7 +280,7 @@ if (opprop != 0) { printk("OpenPIC addrs: %lx %lx %lx\n", opprop[0], opprop[1], opprop[2]); - OpenPIC = ioremap(opprop[0], sizeof(struct OpenPIC)); + OpenPIC_Addr = ioremap(opprop[0], 0x40000); } } #endif @@ -292,23 +293,17 @@ conswitchp = &dummy_con; #endif -#ifndef CONFIG_PPC64BRIDGE - pmac_find_bridges(); -#endif /* CONFIG_PPC64BRIDGE */ - /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort */ - if ( rtas_data ) - { + if ( rtas_data ) { struct property *p; device = find_devices("rtas"); for ( p = device->properties; p && strncmp(p->name, "rtas-event-scan-rate", 20); p = p->next ) /* nothing */ ; - if ( p && *(unsigned long *)p->value ) - { + if ( p && *(unsigned long *)p->value ) { ppc_md.heartbeat = chrp_event_scan; ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1; ppc_md.heartbeat_count = 1; @@ -365,79 +360,44 @@ } } -int __chrp chrp_get_irq( struct pt_regs *regs ) -{ - int irq; - - irq = openpic_irq( smp_processor_id() ); - if (irq == IRQ_8259_CASCADE) - { - /* - * This magic address generates a PCI IACK cycle. - */ - if ( chrp_int_ack_special ) - irq = *chrp_int_ack_special; - else - irq = i8259_irq( smp_processor_id() ); - openpic_eoi( smp_processor_id() ); - } - if (irq == OPENPIC_VEC_SPURIOUS) - /* - * Spurious interrupts should never be - * acknowledged - */ - irq = -1; - /* - * I would like to openpic_eoi here but there seem to be timing problems - * between the openpic ack and the openpic eoi. - * -- Cort - */ - return irq; -} - -void __chrp chrp_post_irq(struct pt_regs* regs, int irq) -{ - /* - * If it's an i8259 irq then we've already done the - * openpic irq. So we just check to make sure the controller - * is an openpic and if it is then eoi - * - * We do it this way since our irq_desc[irq].handler can change - * with RTL and no longer be open_pic -- Cort - */ - if ( irq >= open_pic_irq_offset) - openpic_eoi( smp_processor_id() ); -} - void __init chrp_init_IRQ(void) { struct device_node *np; int i; unsigned long *addrp; + unsigned char* chrp_int_ack_special = 0; + unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; + int nmi_irq = -1; +#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON) + struct device_node *kbd; +#endif if (!(np = find_devices("pci")) || !(addrp = (unsigned long *) get_property(np, "8259-interrupt-acknowledge", NULL))) printk("Cannot find pci to get ack address\n"); else - chrp_int_ack_special = (volatile unsigned char *) - ioremap(*addrp, 1); - open_pic_irq_offset = 16; - for ( i = 16 ; i < NR_IRQS ; i++ ) - irq_desc[i].handler = &open_pic; - openpic_init(1); - enable_irq(IRQ_8259_CASCADE); - for ( i = 0 ; i < 16 ; i++ ) + chrp_int_ack_special = (unsigned char *)ioremap(*addrp, 1); + /* hydra still sets OpenPIC_InitSenses to a static set of values */ + if (OpenPIC_InitSenses == NULL) { + prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS); + OpenPIC_InitSenses = init_senses; + OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS; + } + openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq); + for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) irq_desc[i].handler = &i8259_pic; i8259_init(); -#ifdef CONFIG_XMON - request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI), - xmon_irq, 0, "NMI", 0); -#endif /* CONFIG_XMON */ -#ifdef CONFIG_SMP - request_irq(openpic_to_irq(OPENPIC_VEC_IPI), - openpic_ipi_action, 0, "IPI0", 0); -#endif /* CONFIG_SMP */ +#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON) + /* see if there is a keyboard in the device tree + with a parent of type "adb" */ + for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) + if (kbd->parent && kbd->parent->type + && strcmp(kbd->parent->type, "adb") == 0) + break; + if (kbd) + request_irq( HYDRA_INT_ADB_NMI, xmon_irq, 0, "XMON break", 0); +#endif } void __init @@ -556,12 +516,6 @@ } void __chrp -chrp_ide_fix_driveid(struct hd_driveid *id) -{ - ppc_generic_ide_fix_driveid(id); -} - -void __chrp chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; @@ -586,7 +540,6 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - chrp_setup_pci_ptrs(); #ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ if ( r6 ) @@ -596,10 +549,10 @@ } #endif /* CONFIG_BLK_DEV_INITRD */ - /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */ ISA_DMA_THRESHOLD = ~0L; DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; + isa_io_base = CHRP_ISA_IO_BASE; /* default value */ ppc_md.setup_arch = chrp_setup_arch; ppc_md.setup_residual = NULL; @@ -607,8 +560,8 @@ ppc_md.irq_cannonicalize = chrp_irq_cannonicalize; #ifndef CONFIG_POWER4 ppc_md.init_IRQ = chrp_init_IRQ; - ppc_md.get_irq = chrp_get_irq; - ppc_md.post_irq = chrp_post_irq; + ppc_md.get_irq = openpic_get_irq; + ppc_md.post_irq = NULL; #else ppc_md.init_IRQ = xics_init_IRQ; ppc_md.get_irq = xics_get_irq; @@ -669,11 +622,12 @@ ppc_ide_md.ide_check_region = chrp_ide_check_region; ppc_ide_md.ide_request_region = chrp_ide_request_region; ppc_ide_md.ide_release_region = chrp_ide_release_region; - ppc_ide_md.fix_driveid = chrp_ide_fix_driveid; + ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports; ppc_ide_md.io_base = _IO_BASE; #endif + /* * Print the banner, then scroll down so boot progress * can be printed. -- Cort diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/entry.S linux.ac/arch/ppc/kernel/entry.S --- linux-2.4.0/arch/ppc/kernel/entry.S Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/kernel/entry.S Mon Dec 18 20:42:37 2000 @@ -234,7 +234,6 @@ li r0,0x0ff0 stw r0,TRAP(r1) stw r1,KSP(r3) /* Set old stack pointer */ - sync tophys(r0,r4) CLR_TOP32(r0) mtspr SPRG3,r0 /* Update current THREAD phys addr */ @@ -251,7 +250,7 @@ #endif mtspr M_TWB,r9 /* Update MMU base address */ tlbia - SYNC + sync #endif /* CONFIG_8xx */ lwz r1,KSP(r4) /* Load new stack pointer */ /* save the old current 'last' for return value */ @@ -342,23 +341,23 @@ do_bottom_half_ret: 2: lwz r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR - beq+ restore /* if so, check need_resched and signals */ - .globl ret_to_user_hook -ret_to_user_hook: - nop + beq+ do_signal_ret /* if so, check need_resched and signals */ lwz r3,NEED_RESCHED(r2) cmpi 0,r3,0 /* check need_resched flag */ beq+ 7f bl schedule 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */ cmpwi 0,r5,0 - beq+ restore + beq+ do_signal_ret li r3,0 addi r4,r1,STACK_FRAME_OVERHEAD MOL_HOOK_MMU(8,r8) bl do_signal .globl do_signal_ret do_signal_ret: + .globl ret_to_user_hook +ret_to_user_hook: + nop restore: lwz r3,_XER(r1) mtspr XER,r3 @@ -372,7 +371,7 @@ */ mfmsr r0 /* Get current interrupt state */ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ - sync /* Some chip revs have problems here... */ + SYNC /* Some chip revs have problems here... */ mtmsr r0 /* Update machine state */ /* if returning to user mode, set new sprg2 and save kernel SP */ @@ -468,7 +467,7 @@ andc r0,r9,r0 li r10,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP andc r9,r0,r10 - sync /* disable interrupts so SRR0/1 */ + SYNC /* disable interrupts so SRR0/1 */ mtmsr r0 /* don't get trashed */ mtlr r6 CLR_TOP32(r7) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/error_log.c linux.ac/arch/ppc/kernel/error_log.c --- linux-2.4.0/arch/ppc/kernel/error_log.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/kernel/error_log.c Thu Dec 21 21:33:07 2000 @@ -0,0 +1,179 @@ +/* + * arch/ppc/kernel/error_log.c + * + * Copyright (c) 2000 Tilmann Bitterberg + * (tilmann@bitterberg.de) + * + * Error processing of errors found by rtas even-scan routine + * which is done with every heartbeat. (chrp_setup.c) + */ + +#include + +#include + +#include "error_log.h" + +/* ****************************************************************** */ +/* + * EVENT-SCAN + * The whole stuff below here doesn't take any action when it found + * an error, it just prints as much information as possible and + * then its up to the user to decide what to do. + * + * Returns 0 if no errors were found + * Returns 1 if there may be more errors + */ +int ppc_rtas_errorlog_scan(void) +{ +const char *_errlog_severity[] = { +#ifdef VERBOSE_ERRORS + "No Error\n\t\ +Should require no further information", + "Event\n\t\ +This is not really an error, it is an event. I use events\n\t\ +to communicate with RTAS back and forth.", + "Warning\n\t\ +Indicates a non-state-losing error, either fully recovered\n\t\ +by RTAS or not needing recovery. Ignore it.", + "Error sync\n\t\ +May only be fatal to a certain program or thread. Recovery\n\t\ +and continuation is possible, if I only had a handler for\n\t\ +this. Less serious", + "Error\n\t\ +Less serious, but still causing a loss of data and state.\n\t\ +I can't tell you exactly what to do, You have to decide\n\t\ +with help from the target and initiator field, what kind\n\t\ +of further actions may take place.", + "Fatal\n\t\ +Represent a permanent hardware failure and I believe this\n\t\ +affects my overall performance and behaviour. I would not\n\t\ +attempt to continue normal operation." +#else + "No Error", + "Event", + "Warning", + "Error sync", + "Error", + "Fatal" +#endif /* VERBOSE_ERRORS */ +}; + +const char *_errlog_disposition[] = { +#ifdef VERBOSE_ERRORS + "Fully recovered\n\t\ +There was an error, but it is fully recovered by RTAS.", + "Limited recovery\n\t\ +RTAS was able to recover the state of the machine, but some\n\t\ +feature of the machine has been disabled or lost (for example\n\t\ +error checking) or performance may suffer.", + "Not recovered\n\t\ +Whether RTAS did not try to recover anything or recovery failed:\n\t\ +HOUSTON, WE HAVE A PROBLEM!" +#else + "Fully recovered", + "Limited recovery", + "Not recovered" +#endif /* VERBOSE_ERRORS */ +}; + +const char *_errlog_extended[] = { +#ifdef VERBOSE_ERRORS + "Not present\n\t\ +Sad, the RTAS call didn't return an extended error log.", + "Present\n\t\ +The extended log is present and hopefully it contains a lot of\n\t\ +useful information, which leads to the solution of the problem." +#else + "Not present", + "Present" +#endif /* VERBOSE_ERRORS */ +}; + +const char *_errlog_initiator[] = { + "Unknown or not applicable", + "CPU", + "PCI", + "ISA", + "Memory", + "Power management" +}; + +const char *_errlog_target[] = { + "Unknown or not applicable", + "CPU", + "PCI", + "ISA", + "Memory", + "Power management" +}; + rtas_error_log error_log; + char logdata[1024]; + int error; + int retries = 0; /* if HW error, try 10 times */ + + error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log, + INTERNAL_ERROR | EPOW_WARNING, + 0, __pa(logdata), 1024); + + if (error == 1) /* no errors found */ + return 0; + + if (error == -1) { + printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n"); + return 0; + } + if (error_log.version != 1) + printk(KERN_WARNING "Unknown version (%d), please implement me\n", + error_log.version); + + switch (error_log.disposition) { + case DISP_FULLY_RECOVERED: + /* there was an error, but everything is fine now */ + return 0; + case DISP_NOT_RECOVERED: + printk("We have a really serious Problem!\n"); + case DISP_LIMITED_RECOVERY: + printk("Error classification\n"); + printk("Severity : %s\n", + ppc_rtas_errorlog_check_severity (error_log)); + printk("Initiator : %s\n", + ppc_rtas_errorlog_check_initiator (error_log)); + printk("Target : %s\n", + ppc_rtas_errorlog_check_target (error_log)); + printk("Type : %s\n", + ppc_rtas_errorlog_check_type (error_log)); + printk("Ext. log : %s\n", + ppc_rtas_errorlog_check_extended (error_log)); + if (error_log.extended) + ppc_rtas_errorlog_disect_extended (logdata); + return 1; + default: + /* nothing */ + break; + } + return 0; +} +/* ****************************************************************** */ +const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log) +{ + const char *_errlog_type[] = { + "unknown type", + "too many tries failed", + "TCE error", + "RTAS device failed", + "target timed out", + "parity error on data", /* 5 */ + "parity error on address", + "parity error on external cache", + "access to invalid address", + "uncorrectable ECC error", + "corrected ECC error" /* 10 */ + }; + if (error_log.type == TYPE_EPOW) + return "EPOW"; + if (error_log.type >= TYPE_PMGM_POWER_SW_ON) + return "PowerMGM Event (not handled right now)"; + return _errlog_type[error_log.type]; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/error_log.h linux.ac/arch/ppc/kernel/error_log.h --- linux-2.4.0/arch/ppc/kernel/error_log.h Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/kernel/error_log.h Mon Dec 18 20:42:50 2000 @@ -0,0 +1,95 @@ +#ifndef __ERROR_LOG_H__ +#define __ERROR_LOG_H__ + +#define VERBOSE_ERRORS 1 /* Maybe I enlarge the kernel too much */ +#undef VERBOSE_ERRORS + +/* Event classes */ +/* XXX: Endianess correct? NOW*/ +#define INTERNAL_ERROR 0x80000000 /* set bit 0 */ +#define EPOW_WARNING 0x40000000 /* set bit 1 */ +#define POWERMGM_EVENTS 0x20000000 /* set bit 2 */ + +/* event-scan returns */ +#define SEVERITY_FATAL 0x5 +#define SEVERITY_ERROR 0x4 +#define SEVERITY_ERROR_SYNC 0x3 +#define SEVERITY_WARNING 0x2 +#define SEVERITY_EVENT 0x1 +#define SEVERITY_NO_ERROR 0x0 +#define DISP_FULLY_RECOVERED 0x0 +#define DISP_LIMITED_RECOVERY 0x1 +#define DISP_NOT_RECOVERED 0x2 +#define PART_PRESENT 0x0 +#define PART_NOT_PRESENT 0x1 +#define INITIATOR_UNKNOWN 0x0 +#define INITIATOR_CPU 0x1 +#define INITIATOR_PCI 0x2 +#define INITIATOR_ISA 0x3 +#define INITIATOR_MEMORY 0x4 +#define INITIATOR_POWERMGM 0x5 +#define TARGET_UNKNOWN 0x0 +#define TARGET_CPU 0x1 +#define TARGET_PCI 0x2 +#define TARGET_ISA 0x3 +#define TARGET_MEMORY 0x4 +#define TARGET_POWERMGM 0x5 +#define TYPE_RETRY 0x01 +#define TYPE_TCE_ERR 0x02 +#define TYPE_INTERN_DEV_FAIL 0x03 +#define TYPE_TIMEOUT 0x04 +#define TYPE_DATA_PARITY 0x05 +#define TYPE_ADDR_PARITY 0x06 +#define TYPE_CACHE_PARITY 0x07 +#define TYPE_ADDR_INVALID 0x08 +#define TYPE_ECC_UNCORR 0x09 +#define TYPE_ECC_CORR 0x0a +#define TYPE_EPOW 0x40 +/* I don't add PowerMGM events right now, this is a different topic */ +#define TYPE_PMGM_POWER_SW_ON 0x60 +#define TYPE_PMGM_POWER_SW_OFF 0x61 +#define TYPE_PMGM_LID_OPEN 0x62 +#define TYPE_PMGM_LID_CLOSE 0x63 +#define TYPE_PMGM_SLEEP_BTN 0x64 +#define TYPE_PMGM_WAKE_BTN 0x65 +#define TYPE_PMGM_BATTERY_WARN 0x66 +#define TYPE_PMGM_BATTERY_CRIT 0x67 +#define TYPE_PMGM_SWITCH_TO_BAT 0x68 +#define TYPE_PMGM_SWITCH_TO_AC 0x69 +#define TYPE_PMGM_KBD_OR_MOUSE 0x6a +#define TYPE_PMGM_ENCLOS_OPEN 0x6b +#define TYPE_PMGM_ENCLOS_CLOSED 0x6c +#define TYPE_PMGM_RING_INDICATE 0x6d +#define TYPE_PMGM_LAN_ATTENTION 0x6e +#define TYPE_PMGM_TIME_ALARM 0x6f +#define TYPE_PMGM_CONFIG_CHANGE 0x70 +#define TYPE_PMGM_SERVICE_PROC 0x71 + +typedef struct _rtas_error_log { + unsigned long version:8; /* Architectural version */ + unsigned long severity:3; /* Severity level of error */ + unsigned long disposition:2; /* Degree of recovery */ + unsigned long extended:1; /* extended log present? */ + unsigned long /* reserved */ :2; /* Reserved for future use */ + unsigned long initiator:4; /* Initiator of event */ + unsigned long target:4; /* Target of failed operation */ + unsigned long type:8; /* General event or error*/ + unsigned long extended_log_length:32; /* length in bytes */ +} rtas_error_log; + +/* ****************************************************************** */ +#define ppc_rtas_errorlog_check_severity(x) \ + (_errlog_severity[x.severity]) +#define ppc_rtas_errorlog_check_target(x) \ + (_errlog_target[x.target]) +#define ppc_rtas_errorlog_check_initiator(x) \ + (_errlog_initiator[x.initiator]) +#define ppc_rtas_errorlog_check_extended(x) \ + (_errlog_extended[x.extended]) +#define ppc_rtas_errorlog_disect_extended(x) \ + do { /* implement me */ } while(0) +extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log); +extern int ppc_rtas_errorlog_scan(void); + + +#endif /* __ERROR_LOG_H__ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/feature.c linux.ac/arch/ppc/kernel/feature.c --- linux-2.4.0/arch/ppc/kernel/feature.c Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/kernel/feature.c Mon Dec 18 20:42:50 2000 @@ -238,12 +238,15 @@ static struct feature_controller* feature_lookup_controller(struct device_node *device); +#ifdef CONFIG_PMAC_PBOOK static void heathrow_prepare_for_sleep(struct feature_controller* ctrler); static void heathrow_wakeup(struct feature_controller* ctrler); -static void keylargo_init(void); -static void uninorth_init(void); static void core99_prepare_for_sleep(struct feature_controller* ctrler); static void core99_wake_up(struct feature_controller* ctrler); +#endif /* CONFIG_PMAC_PBOOK */ + +static void keylargo_init(void); +static void uninorth_init(void); /* static variables */ static struct feature_controller controllers[MAX_FEATURE_CONTROLLERS]; @@ -255,6 +258,10 @@ static int uninorth_rev; static int keylargo_rev; +/* + * WARNING ! This function is called early in setup_arch, neither the IO base + * nor the udelay calibration have been done yet + */ void feature_init(void) { @@ -527,14 +534,31 @@ void feature_set_firewire_power(struct device_node* device, int power) { + if (!uninorth_base) + return; + if (power) + UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); + else + UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); + udelay(20); +} + +#ifdef CONFIG_SMP +void +feature_core99_kick_cpu1(void) +{ + out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_UP); + udelay(1); + out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_DOWN); } +#endif /* CONFIG_SMP */ /* Initialize the Core99 UniNorth host bridge and memory controller */ static void uninorth_init(void) { - struct device_node* gmac; + struct device_node* gmac, *fw; unsigned long actrl; /* Set the arbitrer QAck delay according to what Apple does @@ -564,6 +588,11 @@ } if (gmac) feature_set_gmac_power(gmac, 0); + + /* Kludge (enable FW before PCI probe) */ + fw = find_devices("firewire"); + if (fw && device_is_compatible(fw, "pci106b,18")) + feature_set_firewire_power(fw, 1); } /* Initialize the Core99 KeyLargo ASIC. Currently, we just make sure @@ -576,6 +605,43 @@ } #ifdef CONFIG_PMAC_PBOOK + +static u32 save_fcr[5]; +static u32 save_mbcr; + +static void +heathrow_prepare_for_sleep(struct feature_controller* ctrler) +{ + save_mbcr = in_le32(FREG(ctrler, 0x34)); + save_fcr[0] = in_le32(FREG(ctrler, 0x38)); + save_fcr[1] = in_le32(FREG(ctrler, 0x3c)); + + out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE); +} + +static void +heathrow_wakeup(struct feature_controller* ctrler) +{ + out_le32(FREG(ctrler, 0x38), save_fcr[0]); + out_le32(FREG(ctrler, 0x3c), save_fcr[1]); + out_le32(FREG(ctrler, 0x34), save_mbcr); + mdelay(1); + out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE); + mdelay(1); +} + +static void +core99_prepare_for_sleep(struct feature_controller* ctrler) +{ + /* Not yet implemented */ +} + +static void +core99_wake_up(struct feature_controller* ctrler) +{ + /* Not yet implemented */ +} + void feature_prepare_for_sleep(void) { @@ -599,7 +665,6 @@ } } - void feature_wake_up(void) { @@ -622,39 +687,4 @@ } } -static u32 save_fcr[5]; -static u32 save_mbcr; - -static void -heathrow_prepare_for_sleep(struct feature_controller* ctrler) -{ - save_mbcr = in_le32(FREG(ctrler, 0x34)); - save_fcr[0] = in_le32(FREG(ctrler, 0x38)); - save_fcr[1] = in_le32(FREG(ctrler, 0x3c)); - - out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE); -} - -static void -heathrow_wakeup(struct feature_controller* ctrler) -{ - out_le32(FREG(ctrler, 0x38), save_fcr[0]); - out_le32(FREG(ctrler, 0x3c), save_fcr[1]); - out_le32(FREG(ctrler, 0x34), save_mbcr); - mdelay(1); - out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE); - mdelay(1); -} - -static void -core99_prepare_for_sleep(struct feature_controller* ctrler) -{ - /* Not yet implemented */ -} - -static void -core99_wake_up(struct feature_controller* ctrler) -{ - /* Not yet implemented */ -} #endif /* CONFIG_PMAC_PBOOK */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/galaxy_pci.c linux.ac/arch/ppc/kernel/galaxy_pci.c --- linux-2.4.0/arch/ppc/kernel/galaxy_pci.c Thu Feb 10 20:37:51 2000 +++ linux.ac/arch/ppc/kernel/galaxy_pci.c Mon Dec 18 20:42:50 2000 @@ -36,67 +36,84 @@ /* Function Prototypes */ -decl_config_access_method(galaxy); - - void __init galaxy_pcibios_fixup(void) { } -void __init -galaxy_setup_pci_ptrs(void) +static int +galaxy_pcibios_read_config_byte(struct pci_controller* hose, + u8 bus, u8 dev, u8 offset, u8 *val) { - set_config_access_method(galaxy); - ppc_md.pcibios_fixup = galaxy_pcibios_fixup; + return (PCIBIOS_SUCCESSFUL); } -int -galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) +static int +galaxy_pcibios_read_config_word(struct pci_controller* hose, + u8 bus, u8 dev, u8 offset, u16 *val) { return (PCIBIOS_SUCCESSFUL); } -int -galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) +static int +galaxy_pcibios_read_config_dword(struct pci_controller* hose, + u8 bus, u8 dev, u8 offset, u32 *val) { return (PCIBIOS_SUCCESSFUL); } -int -galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) +static int +galaxy_pcibios_write_config_byte(struct pci_controller* hose, + u8 bus, u8 dev, u8 offset, u8 val) { return (PCIBIOS_SUCCESSFUL); } -int -galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) +static int +galaxy_pcibios_write_config_word(struct pci_controller* hose, + u8 bus, u8 dev, u8 offset, u16 val) { return (PCIBIOS_SUCCESSFUL); } -int -galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) +static int +galaxy_pcibios_write_config_dword(struct pci_controller* hose, + u8 bus, u8 dev, u8 offset, u32 val) { return (PCIBIOS_SUCCESSFUL); } -int -galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) +static struct pci_controller_ops galaxy_pci_ops = { + galaxy_pcibios_read_config_byte, + galaxy_pcibios_read_config_word, + galaxy_pcibios_read_config_dword, + galaxy_pcibios_write_config_byte, + galaxy_pcibios_write_config_word, + galaxy_pcibios_write_config_dword +}; - return (PCIBIOS_SUCCESSFUL); +void __init +galaxy_find_bridges(void) +{ + struct pci_controller* hose; + + set_config_access_method(galaxy); + + ppc_md.pcibios_fixup = galaxy_pcibios_fixup; + hose = pcibios_alloc_controller(); + if (!hose) + return; + hose->ops = &galaxy_pci_ops; + /* Todo ... + hose->cfg_data = ioremap(PCICFGDATA, ...); + hose->cfg_addr = ioremap(PCICFGADDR, ...); + */ } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/gemini_pci.c linux.ac/arch/ppc/kernel/gemini_pci.c --- linux-2.4.0/arch/ppc/kernel/gemini_pci.c Tue May 2 21:05:39 2000 +++ linux.ac/arch/ppc/kernel/gemini_pci.c Mon Dec 18 20:42:50 2000 @@ -8,6 +8,7 @@ #include #include #include +#include #include "pci.h" @@ -16,67 +17,79 @@ int -gemini_pcibios_read_config_byte(unsigned char bus, unsigned char dev, - unsigned char offset, unsigned char *val) +gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val) { unsigned long reg; - reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3)))); + reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn, + (offset & ~(0x3)))); *val = ((reg >> ((offset & 0x3) << 3)) & 0xff); return PCIBIOS_SUCCESSFUL; } int -gemini_pcibios_read_config_word(unsigned char bus, unsigned char dev, - unsigned char offset, unsigned short *val) +gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val) { unsigned long reg; - reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3)))); + reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn, + (offset & ~(0x3)))); *val = ((reg >> ((offset & 0x3) << 3)) & 0xffff); return PCIBIOS_SUCCESSFUL; } int -gemini_pcibios_read_config_dword(unsigned char bus, unsigned char dev, - unsigned char offset, unsigned int *val) +gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val) { - *val = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3)))); + *val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn, + (offset & ~(0x3)))); return PCIBIOS_SUCCESSFUL; } int -gemini_pcibios_write_config_byte(unsigned char bus, unsigned char dev, - unsigned char offset, unsigned char val) +gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val) { unsigned long reg; int shifts = offset & 0x3; + unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn, + (offset & ~(0x3))) - reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3)))); + reg = grackle_read(addr); reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3)); - grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg ); + grackle_write(addr, reg ); return PCIBIOS_SUCCESSFUL; } int -gemini_pcibios_write_config_word(unsigned char bus, unsigned char dev, - unsigned char offset, unsigned short val) +gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val) { unsigned long reg; int shifts = offset & 0x3; + unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn, + (offset & ~(0x3))) - reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3)))); + reg = grackle_read(addr); reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3)); - grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg ); + grackle_write(addr, reg ); return PCIBIOS_SUCCESSFUL; } int -gemini_pcibios_write_config_dword(unsigned char bus, unsigned char dev, - unsigned char offset, unsigned int val) +gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val) { - grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), val ); + grackle_write(pci_config_addr(dev->bus->number, dev->devfn, + (offset & ~(0x3))), val); return PCIBIOS_SUCCESSFUL; } +static struct pci_ops gemini_pci_ops = +{ + gemini_read_config_byte, + gemini_read_config_word, + gemini_read_config_dword, + gemini_write_config_byte, + gemini_write_config_word, + gemini_write_config_dword +}; + void __init gemini_pcibios_fixup(void) { int i; @@ -92,12 +105,17 @@ } } -decl_config_access_method(gemini); /* The "bootloader" for Synergy boards does none of this for us, so we need to lay it all out ourselves... --Dan */ -void __init gemini_setup_pci_ptrs(void) +void __init gemini_find_bridges(void) { - set_config_access_method(gemini); + struct pci_controller* hose; + ppc_md.pcibios_fixup = gemini_pcibios_fixup; + + hose = pcibios_alloc_controller(); + if (!hose) + return; + hose->ops = &gemini_pci_ops; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/gemini_prom.S linux.ac/arch/ppc/kernel/gemini_prom.S --- linux-2.4.0/arch/ppc/kernel/gemini_prom.S Mon Apr 24 21:39:36 2000 +++ linux.ac/arch/ppc/kernel/gemini_prom.S Mon Dec 18 20:42:50 2000 @@ -39,6 +39,7 @@ ori r3,r3,MSR_IR|MSR_DR andc r4,r4,r3 mtmsr r4 + isync #if 0 /* zero out the bats now that the MMU is off */ prom_no_mmu: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/gemini_setup.c linux.ac/arch/ppc/kernel/gemini_setup.c --- linux-2.4.0/arch/ppc/kernel/gemini_setup.c Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/kernel/gemini_setup.c Fri Dec 22 16:34:39 2000 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -30,12 +29,12 @@ #include #include #include - #include + #include "local_irq.h" #include "open_pic.h" -void gemini_setup_pci_ptrs(void); +void gemini_find_bridges(void); static int gemini_get_clock_speed(void); extern void gemini_pcibios_fixup(void); @@ -116,23 +115,15 @@ void __init gemini_openpic_init(void) { - OpenPIC = (volatile struct OpenPIC *) - grackle_read(0x80005800 + 0x10); -#if 0 - grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0, - GEMINI_MPIC_ADDR); - grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY); - - OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR; -#endif + OpenPIC_Addr = grackle_read(GEMINI_MPIC_PCI_CFG + 0x10); OpenPIC_InitSenses = gemini_openpic_initsenses; OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses ); - ioremap( GEMINI_MPIC_ADDR, sizeof( struct OpenPIC )); + ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE); } -extern unsigned long loops_per_sec; +extern unsigned long loops_per_jiffy; extern int root_mountflags; extern char cmd_line[]; @@ -155,7 +146,7 @@ extern char cmd_line[]; - loops_per_sec = 50000000; + loops_per_jiffy = 50000000/HZ; #ifdef CONFIG_BLK_DEV_INITRD /* bootable off CDROM */ @@ -174,6 +165,8 @@ ppc_md.heartbeat_reset = HZ/8; ppc_md.heartbeat_count = 1; + /* Lookup PCI hosts */ + gemini_find_bridges(); /* take special pains to map the MPIC, since it isn't mapped yet */ gemini_openpic_init(); /* start the L2 */ @@ -213,13 +206,6 @@ return clock; } -#define L2CR_PIPE_LATEWR (0x01800000) /* late-write SRAM */ -#define L2CR_L2CTL (0x00100000) /* RAM control */ -#define L2CR_INST_DISABLE (0x00400000) /* disable for insn's */ -#define L2CR_L2I (0x00200000) /* global invalidate */ -#define L2CR_L2E (0x80000000) /* enable */ -#define L2CR_L2WT (0x00080000) /* write-through */ - void __init gemini_init_l2(void) { unsigned char reg, brev, fam, creg; @@ -286,7 +272,7 @@ cache |= ((1<>2)&0x3) { case 0: default: - freq = 66; + freq = 66667; break; case 1: - freq = 83; + freq = 83000; break; case 2: - freq = 100; + freq = 100000; break; } - freq *= 1000000; + freq *= 1000; divisor = 4; - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; -} - -int gemini_get_irq( struct pt_regs *regs ) -{ - int irq; - - irq = openpic_irq( smp_processor_id() ); - if (irq == OPENPIC_VEC_SPURIOUS) - /* - * Spurious interrupts should never be - * acknowledged - */ - irq = -1; - /* - * I would like to openpic_eoi here but there seem to be timing problems - * between the openpic ack and the openpic eoi. - * -- Cort - */ - return irq; -} - -void gemini_post_irq(struct pt_regs* regs, int irq) -{ - /* - * If it's an i8259 irq then we've already done the - * openpic irq. So we just check to make sure the controller - * is an openpic and if it is then eoi - * - * We do it this way since our irq_desc[irq].handler can change - * with RTL and no longer be open_pic -- Cort - */ - if ( irq >= open_pic_irq_offset) - openpic_eoi( smp_processor_id() ); + tb_ticks_per_jiffy = freq / HZ / divisor; + tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); } - void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { @@ -516,8 +452,6 @@ for(i = 0; i < GEMINI_LEDS; i++) gemini_led_off(i); - gemini_setup_pci_ptrs(); - ISA_DMA_THRESHOLD = 0; DMA_MODE_READ = 0; DMA_MODE_WRITE = 0; @@ -535,8 +469,8 @@ ppc_md.get_cpuinfo = gemini_get_cpuinfo; ppc_md.irq_cannonicalize = NULL; ppc_md.init_IRQ = gemini_init_IRQ; - ppc_md.get_irq = gemini_get_irq; - ppc_md.post_irq = gemini_post_irq; + ppc_md.get_irq = openpic_get_irq; + ppc_md.post_irq = NULL; ppc_md.init = NULL; ppc_md.restart = gemini_restart; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/hashtable.S linux.ac/arch/ppc/kernel/hashtable.S --- linux-2.4.0/arch/ppc/kernel/hashtable.S Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/kernel/hashtable.S Wed Jan 3 17:08:57 2001 @@ -56,7 +56,6 @@ #ifdef CONFIG_PPC64BRIDGE mfmsr r0 clrldi r0,r0,1 /* make sure it's in 32-bit mode */ - sync MTMSRD(r0) isync #endif @@ -112,23 +111,31 @@ #endif tophys(r2,r5) 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 */ + rlwinm r5,r4,5,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */ + rlwimi r5,r4,7,22,22 /* _PAGE_RW -> _PAGE_HWWRITE */ + ori r5,r5,0x100 /* set _PAGE_ACCESSED */ +retry: + lwz r6,0(r2) /* get linux-style pte */ andc. r0,r4,r6 /* check access & ~permission */ #ifdef CONFIG_SMP bne- hash_page_out /* return if access not permitted */ #else bnelr- #endif + andc. r0,r5,r6 /* any bits not yet set? */ + beq 2f - ori r6,r6,0x100 /* set _PAGE_ACCESSED in pte */ - rlwinm r5,r4,5,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */ - rlwimi r5,r4,7,22,22 /* _PAGE_RW -> _PAGE_HWWRITE */ - or r6,r6,r5 - stw r6,0(r2) /* update PTE (accessed/dirty bits) */ + /* Update the linux PTE atomically */ + lwarx r0,0,r2 /* refetch the pte and check */ + cmpw 0,r0,r6 /* that it hasn't been changed */ + bne- retry /* retry if it has */ + or r6,r6,r5 /* set accessed/dirty bits */ + stwcx. r6,0,r2 /* attempt to update PTE */ + bne- retry /* retry if someone got there first */ /* Convert linux-style PTE to low word of PPC-style PTE */ - rlwinm r4,r6,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */ +2: rlwinm r4,r6,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */ rlwimi r6,r6,32-1,31,31 /* _PAGE_USER -> PP (both bits now) */ ori r4,r4,0xe04 /* clear out reserved bits */ andc r6,r6,r4 /* PP=2 or 0, when _PAGE_HWWRITE */ @@ -166,12 +173,16 @@ rlwimi r4,r5,32-5,25-Hash_bits,24 /* (VSID & hash_mask) << 7 */ rlwinm r0,r3,32-5,25-Hash_bits,24 /* (PI & hash_mask) << 7 */ xor r4,r4,r0 /* make primary hash */ + li r2,8 /* PTEs/group */ +#ifndef CONFIG_SMP + /* We don't do this for SMP - another cpu could have put in + the appropriate PTE since we took the exception. -- paulus. */ /* See whether it was a PTE not found exception or a protection violation. */ andis. r0,r20,0x4000 - li r2,8 /* PTEs/group */ bne 10f /* no PTE: go look for an empty slot */ +#endif /* CONFIG_SMP */ tlbie r3 /* invalidate TLB entry */ /* Search the primary PTEG for a PTE whose 1st dword matches r5 */ @@ -263,7 +274,6 @@ std r5,0(r3) found_slot: std r6,8(r3) - sync #else /* CONFIG_SMP */ /* @@ -311,12 +321,16 @@ rlwimi r4,r5,32-1,26-Hash_bits,25 /* (VSID & hash_mask) << 6 */ rlwinm r0,r3,32-6,26-Hash_bits,25 /* (PI & hash_mask) << 6 */ xor r4,r4,r0 /* make primary hash */ + li r2,8 /* PTEs/group */ +#ifndef CONFIG_SMP + /* We don't do this for SMP - another cpu could have put in + the appropriate PTE since we took the exception. -- paulus. */ /* See whether it was a PTE not found exception or a protection violation. */ andis. r0,r20,0x4000 - li r2,8 /* PTEs/group */ bne 10f /* no PTE: go look for an empty slot */ +#endif /* CONFIG_SMP */ tlbie r3 /* invalidate TLB entry */ /* Search the primary PTEG for a PTE whose 1st word matches r5 */ @@ -394,7 +408,6 @@ stw r5,0(r3) found_slot: stw r6,4(r3) - sync #else /* CONFIG_SMP */ /* @@ -428,6 +441,8 @@ #endif /* CONFIG_SMP */ #endif /* CONFIG_PPC64BRIDGE */ + sync /* make sure pte updates get to memory */ + /* * Update the hash table miss count. We only want misses here * that _are_ valid addresses and have a pte otherwise we don't @@ -517,7 +532,7 @@ a hash table miss while we have the hash table locked, or we'll get a deadlock. -paulus */ mfmsr r10 - sync + SYNC rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ mtmsr r0 SYNC @@ -616,7 +631,7 @@ a hash table miss while we have the hash table locked, or we'll get a deadlock. -paulus */ mfmsr r10 - sync + SYNC rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ mtmsr r0 SYNC @@ -628,10 +643,14 @@ oris r8,r8,9 10: lwarx r7,0,r9 cmpi 0,r7,0 - bne- 10b + bne- 11f stwcx. r8,0,r9 - bne- 10b - eieio + beq+ 12f +11: lwz r7,0(r9) + cmpi 0,r7,0 + beq 10b + b 11b +12: eieio #endif #ifndef CONFIG_PPC64BRIDGE rlwinm r3,r3,11,1,20 /* put context into vsid */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/head.S linux.ac/arch/ppc/kernel/head.S --- linux-2.4.0/arch/ppc/kernel/head.S Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/kernel/head.S Wed Jan 3 17:08:57 2001 @@ -149,6 +149,8 @@ mr r28,r6 mr r27,r7 li r24,0 /* cpu # */ + /* N.B. prom_init clears the BSS even if it doesn't do + * anything else -- paulus. */ bl prom_init #ifdef CONFIG_APUS @@ -290,6 +292,7 @@ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r20,MSR_KERNEL; \ bl transfer_to_handler; \ +i##n: \ .long hdlr; \ .long ret_from_except @@ -301,6 +304,7 @@ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r20,MSR_KERNEL; \ bl transfer_to_handler; \ +i##n: \ .long hdlr; \ .long ret_from_except @@ -344,6 +348,7 @@ li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ bl transfer_to_handler +i0x300: .long do_page_fault .long ret_from_except @@ -384,6 +389,7 @@ li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ bl transfer_to_handler +i0x400: .long do_page_fault .long ret_from_except @@ -429,6 +435,7 @@ li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ bl transfer_to_handler +i0x600: .long AlignmentException .long ret_from_except @@ -441,6 +448,7 @@ li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ bl transfer_to_handler +i0x700: .long ProgramCheckException .long ret_from_except @@ -452,6 +460,7 @@ bne load_up_fpu /* if from user, just load it up */ li r20,MSR_KERNEL bl transfer_to_handler /* if from kernel, take a trap */ +i0x800: .long KernelFP .long ret_from_except @@ -575,7 +584,7 @@ mfmsr r0 /* Restore "normal" registers */ xoris r0,r0,MSR_TGPR>>16 mtcrf 0x80,r3 /* Restore CR0 */ - sync /* Some chip revs have problems here... */ + SYNC /* Some chip revs have problems here... */ mtmsr r0 b InstructionAccess @@ -646,7 +655,7 @@ mfmsr r0 /* Restore "normal" registers */ xoris r0,r0,MSR_TGPR>>16 mtcrf 0x80,r3 /* Restore CR0 */ - sync /* Some chip revs have problems here... */ + SYNC /* Some chip revs have problems here... */ mtmsr r0 b DataAccess @@ -843,7 +852,7 @@ #endif /* CONFIG_PPC64BRIDGE */ SYNC MTMSRD(r5) /* enable use of fpu now */ - SYNC + isync /* * For SMP, we don't do lazy FPU switching because it just gets too * horrendously complex, especially when a task switches from one CPU @@ -929,7 +938,7 @@ oris r5,r5,MSR_VEC@h SYNC mtmsr r5 /* enable use of AltiVec now */ - SYNC + isync /* * For SMP, we don't do lazy AltiVec switching because it just gets too * horrendously complex, especially when a task switches from one CPU @@ -1023,7 +1032,7 @@ oris r5,r5,MSR_VEC@h SYNC mtmsr r5 /* enable use of AltiVec now */ - SYNC + isync cmpi 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ @@ -1064,7 +1073,7 @@ ori r5,r5,MSR_FP SYNC mtmsr r5 /* enable use of fpu now */ - SYNC + isync cmpi 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ @@ -1163,6 +1172,7 @@ icbi r0,r14 /* flush the icache line */ cmpw r12,r13 bne 1b + isync /* * Map the memory where the exception handlers will @@ -1208,9 +1218,9 @@ mfmsr 20 xori r20,r20,MSR_DR - sync + SYNC mtmsr r20 - sync + isync lis r4,APUS_IPL_EMU@h @@ -1243,9 +1253,9 @@ mfmsr r20 xori r20,r20,MSR_DR - sync + SYNC mtmsr r20 - sync + isync stw r3,(_CCR+4)(r21); @@ -1276,15 +1286,26 @@ bl prom_init b __secondary_start #endif /* CONFIG_GEMINI */ - + + /* Temporary horrible hack */ .globl __secondary_start_psurge __secondary_start_psurge: li r24,1 /* cpu # */ + b __secondary_start_psurge99 + .globl __secondary_start_psurge2 +__secondary_start_psurge2: + li r24,2 /* cpu # */ + b __secondary_start_psurge99 + .globl __secondary_start_psurge3 +__secondary_start_psurge3: + li r24,3 /* cpu # */ + b __secondary_start_psurge99 +__secondary_start_psurge99: /* we come in here with IR=0 and DR=1, and DBAT 0 set to map the 0xf0000000 - 0xffffffff region */ mfmsr r0 rlwinm r0,r0,0,28,26 /* clear DR (0x10) */ - sync + SYNC mtmsr r0 isync @@ -1293,7 +1314,7 @@ #ifdef CONFIG_PPC64BRIDGE mfmsr r0 clrldi r0,r0,1 /* make sure it's in 32-bit mode */ - sync + SYNC MTMSRD(r0) isync #else @@ -1445,21 +1466,6 @@ li r3,0 mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ - /* Clear out the BSS */ - lis r11,_end@ha - addi r11,r11,_end@l - lis r8,__bss_start@ha - addi r8,r8,__bss_start@l - subf r11,r8,r11 - addi r11,r11,3 - rlwinm. r11,r11,30,2,31 - beq 2f - addi r8,r8,-4 - mtctr r11 - li r0,0 -3: stwu r0,4(r8) - bdnz 3b -2: /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 @@ -1504,7 +1510,7 @@ RFI /* Load up the kernel context */ 2: - SYNC /* Force all PTE updates to finish */ + sync /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ #ifdef CONFIG_SMP @@ -1745,3 +1751,12 @@ .globl cmd_line cmd_line: .space 512 + + .globl intercept_table +intercept_table: + .long 0, i0x100, i0x200, i0x300, i0x400, 0, i0x600, i0x700 + .long i0x800, 0, 0, 0, 0, i0xd00, 0, 0 + .long 0, 0, 0, i0x1300, 0, 0, 0, 0 + .long 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0, 0, 0, 0, 0, 0, 0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/i8259.c linux.ac/arch/ppc/kernel/i8259.c --- linux-2.4.0/arch/ppc/kernel/i8259.c Tue Jun 20 01:59:36 2000 +++ linux.ac/arch/ppc/kernel/i8259.c Mon Dec 18 20:42:55 2000 @@ -10,12 +10,15 @@ #define cached_A1 (cached_8259[0]) #define cached_21 (cached_8259[1]) +spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED; + int i8259_pic_irq_offset; int i8259_irq(int cpu) { int irq; + spin_lock/*_irqsave*/(&i8259_lock/*, flags*/); /* * Perform an interrupt acknowledge cycle on controller 1 */ @@ -40,14 +43,20 @@ * interrupt */ outb(0x0b, 0x20); - if(~inb(0x20)&0x80) + if(~inb(0x20)&0x80) { + spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/); return -1; + } } + spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/); return irq; } static void i8259_mask_and_ack_irq(unsigned int irq_nr) { + unsigned long flags; + + spin_lock_irqsave(&i8259_lock, flags); if ( irq_nr >= i8259_pic_irq_offset ) irq_nr -= i8259_pic_irq_offset; @@ -63,6 +72,7 @@ outb(cached_21,0x21); outb(0x20,0x20); /* Non-specific EOI */ } + spin_unlock_irqrestore(&i8259_lock, flags); } static void i8259_set_irq_mask(int irq_nr) @@ -73,6 +83,9 @@ static void i8259_mask_irq(unsigned int irq_nr) { + unsigned long flags; + + spin_lock_irqsave(&i8259_lock, flags); if ( irq_nr >= i8259_pic_irq_offset ) irq_nr -= i8259_pic_irq_offset; if ( irq_nr < 8 ) @@ -80,11 +93,14 @@ else cached_A1 |= 1 << (irq_nr-8); i8259_set_irq_mask(irq_nr); + spin_unlock_irqrestore(&i8259_lock, flags); } static void i8259_unmask_irq(unsigned int irq_nr) { + unsigned long flags; + spin_lock_irqsave(&i8259_lock, flags); if ( irq_nr >= i8259_pic_irq_offset ) irq_nr -= i8259_pic_irq_offset; if ( irq_nr < 8 ) @@ -92,6 +108,13 @@ else cached_A1 &= ~(1 << (irq_nr-8)); i8259_set_irq_mask(irq_nr); + spin_unlock_irqrestore(&i8259_lock, flags); +} + +static void i8259_end_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + i8259_unmask_irq(irq); } struct hw_interrupt_type i8259_pic = { @@ -101,11 +124,15 @@ i8259_unmask_irq, i8259_mask_irq, i8259_mask_and_ack_irq, - 0 + i8259_end_irq, + NULL }; void __init i8259_init(void) { + unsigned long flags; + + spin_lock_irqsave(&i8259_lock, flags); /* init master interrupt controller */ outb(0x11, 0x20); /* Start init sequence */ outb(0x00, 0x21); /* Vector base */ @@ -120,7 +147,7 @@ outb(0xFF, 0xA1); /* Mask all */ outb(cached_A1, 0xA1); outb(cached_21, 0x21); + spin_unlock_irqrestore(&i8259_lock, flags); request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT, "82c59 secondary cascade", NULL ); - enable_irq(i8259_pic_irq_offset + 2); /* Enable cascade interrupt */ } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/idle.c linux.ac/arch/ppc/kernel/idle.c --- linux-2.4.0/arch/ppc/kernel/idle.c Sun Sep 17 17:48:06 2000 +++ linux.ac/arch/ppc/kernel/idle.c Wed Jan 3 17:09:05 2001 @@ -47,24 +47,35 @@ int idled(void) { + int do_power_save = 0; + + /* only sleep on the 603-family/750 processors */ + switch (_get_PVR() >> 16) { + case 3: /* 603 */ + case 6: /* 603e */ + case 7: /* 603ev */ + case 8: /* 750 */ + case 12: /* 7400 */ + do_power_save = 1; + } + /* endless loop with no priority at all */ current->nice = 20; current->counter = -100; init_idle(); for (;;) { - __sti(); - - check_pgt_cache(); - - /*if ( !current->need_resched && zero_paged_on ) zero_paged();*/ - if ( !current->need_resched && htab_reclaim_on ) htab_reclaim(); - if ( !current->need_resched ) power_save(); + /*if ( !current->need_resched && zero_paged_on ) + zero_paged();*/ + if (!current->need_resched && htab_reclaim_on) + htab_reclaim(); + if (do_power_save && !current->need_resched) + power_save(); -#ifdef CONFIG_SMP - if (current->need_resched) -#endif + if (current->need_resched) { schedule(); + check_pgt_cache(); + } } return 0; } @@ -278,31 +289,31 @@ void power_save(void) { - unsigned long msr, hid0; - - /* only sleep on the 603-family/750 processors */ - switch (_get_PVR() >> 16) { - case 3: /* 603 */ - case 6: /* 603e */ - case 7: /* 603ev */ - case 8: /* 750 */ - case 12: /* 7400 */ - save_flags(msr); - __cli(); - if (!current->need_resched) { - asm("mfspr %0,1008" : "=r" (hid0) :); - hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE); - hid0 |= (powersave_nap? HID0_NAP: HID0_DOZE) | HID0_DPM; - asm("mtspr 1008,%0" : : "r" (hid0)); + unsigned long hid0; + /* + * Disable interrupts to prevent a lost wakeup + * when going to sleep. This is necessary even with + * RTLinux since we are not guaranteed an interrupt + * didn't come in and is waiting for a __sti() before + * emulating one. This way, we really do hard disable. + * + * We assume that we're sti-ed when we come in here. We + * are in the idle loop so if we're cli-ed then it's a bug + * anyway. + * -- Cort + */ + _nmask_and_or_msr(MSR_EE, 0); + if (!current->need_resched) + { + asm("mfspr %0,1008" : "=r" (hid0) :); + hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE); + hid0 |= (powersave_nap? HID0_NAP: HID0_DOZE) | HID0_DPM; + asm("mtspr 1008,%0" : : "r" (hid0)); - /* set the POW bit in the MSR, and enable interrupts - * so we wake up sometime! */ - __sti(); /* this keeps rtl from getting confused -- Cort */ - _nmask_and_or_msr(0, MSR_POW | MSR_EE); - } - restore_flags(msr); - default: - return; + /* set the POW bit in the MSR, and enable interrupts + * so we wake up sometime! */ + _nmask_and_or_msr(0, MSR_POW | MSR_EE); } + _nmask_and_or_msr(0, MSR_EE); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/indirect_pci.c linux.ac/arch/ppc/kernel/indirect_pci.c --- linux-2.4.0/arch/ppc/kernel/indirect_pci.c Thu Oct 7 18:17:08 1999 +++ linux.ac/arch/ppc/kernel/indirect_pci.c Mon Dec 18 20:43:01 2000 @@ -9,113 +9,59 @@ * 2 of the License, or (at your option) any later version. */ +#include #include -#include -#include - -unsigned int * pci_config_address; -unsigned char * pci_config_data; - -int indirect_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - unsigned long flags; - - save_flags(flags); cli(); - - out_be32(pci_config_address, - ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80); - - *val= in_8(pci_config_data + (offset&3)); - - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} - -int indirect_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - unsigned long flags; - - if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; - - save_flags(flags); cli(); - - out_be32(pci_config_address, - ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80); - - *val= in_le16((unsigned short *)(pci_config_data + (offset&3))); - - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} - -int indirect_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - unsigned long flags; - - if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; - - save_flags(flags); cli(); - - out_be32(pci_config_address, - ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80); - - *val= in_le32((unsigned *)pci_config_data); - - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} +#include +#include +#include +#include -int indirect_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - unsigned long flags; - - save_flags(flags); cli(); - - out_be32(pci_config_address, - ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80); - - out_8(pci_config_data + (offset&3), val); - - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} - -int indirect_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - unsigned long flags; - - if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; - - save_flags(flags); cli(); - - out_be32(pci_config_address, - ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80); - - out_le16((unsigned short *)(pci_config_data + (offset&3)), val); - - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; +#include +#include +#include +#include +#include + +#include "pci.h" + +#define cfg_read(val, addr, type, op) *val = op((type)(addr)) +#define cfg_write(val, addr, type, op) op((type *)(addr), (val)) + +#define INDIRECT_PCI_OP(rw, size, type, op, mask) \ +static int \ +indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + struct pci_controller *hose = dev->sysdata; \ + \ + out_be32(hose->cfg_addr, \ + ((offset & 0xfc) << 24) | (dev->devfn << 16) \ + | (dev->bus->number << 8) | 0x80); \ + cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \ + return PCIBIOS_SUCCESSFUL; \ +} + +INDIRECT_PCI_OP(read, byte, u8 *, in_8, 3) +INDIRECT_PCI_OP(read, word, u16 *, in_le16, 2) +INDIRECT_PCI_OP(read, dword, u32 *, in_le32, 0) +INDIRECT_PCI_OP(write, byte, u8, out_8, 3) +INDIRECT_PCI_OP(write, word, u16, out_le16, 2) +INDIRECT_PCI_OP(write, dword, u32, out_le32, 0) + +static struct pci_ops indirect_pci_ops = +{ + indirect_read_config_byte, + indirect_read_config_word, + indirect_read_config_dword, + indirect_write_config_byte, + indirect_write_config_word, + indirect_write_config_dword +}; + +void __init +setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ + hose->ops = &indirect_pci_ops; + hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4); + hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4); } -int indirect_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - unsigned long flags; - - if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; - - save_flags(flags); cli(); - - out_be32(pci_config_address, - ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80); - - out_le32((unsigned *)pci_config_data, val); - - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/irq.c linux.ac/arch/ppc/kernel/irq.c --- linux-2.4.0/arch/ppc/kernel/irq.c Sun Nov 12 02:19:56 2000 +++ linux.ac/arch/ppc/kernel/irq.c Wed Jan 3 17:09:05 2001 @@ -41,11 +41,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -64,19 +64,22 @@ #include "local_irq.h" -extern volatile unsigned long ipi_count; +atomic_t ipi_recv; +atomic_t ipi_sent; void enable_irq(unsigned int irq_nr); void disable_irq(unsigned int irq_nr); -volatile unsigned char *chrp_int_ack_special; +static void register_irq_proc (unsigned int irq); #define MAXCOUNT 10000000 -irq_desc_t irq_desc[NR_IRQS]; +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = + { [0 ... NR_IRQS-1] = { 0, NULL, NULL, 0, SPIN_LOCK_UNLOCKED}}; + int ppc_spurious_interrupts = 0; struct irqaction *ppc_irq_action[NR_IRQS]; -unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; -unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; +unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; +unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; atomic_t ppc_n_lost_interrupts; /* nasty hack for shared irq's since we need to do kmalloc calls but @@ -115,52 +118,136 @@ kfree(ptr); } +int +setup_irq(unsigned int irq, struct irqaction * new) +{ + int shared = 0; + unsigned long flags; + struct irqaction *old, **p; + irq_desc_t *desc = irq_desc + irq; + + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a + * running system. + */ + if (new->flags & SA_SAMPLE_RANDOM) { + /* + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(irq); + } + + /* + * The following block of code has to be executed atomically + */ + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + desc->depth = 0; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); + unmask_irq(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + register_irq_proc(irq); + return 0; +} + +/* This could be promoted to a real free_irq() ... */ +static int +do_free_irq(int irq, void* dev_id) +{ + irq_desc_t *desc; + struct irqaction **p; + unsigned long flags; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + mask_irq(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + +#ifdef CONFIG_SMP + /* Wait to make sure it's not being used on another CPU */ + while (desc->status & IRQ_INPROGRESS) + barrier(); +#endif + irq_kfree(action); + return 0; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + break; + } + return -ENOENT; +} + #if (defined(CONFIG_8xx) || defined(CONFIG_8260)) /* Name change so we can catch standard drivers that potentially mess up * the internal interrupt controller on 8xx and 8260. Just bear with me, * I don't like this either and I am searching a better solution. For * now, this is what I need. -- Dan */ -int request_8xxirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +#define request_irq request_8xxirq #elif defined(CONFIG_APUS) -int request_sysirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), -#else -int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +#define request_irq request_sysirq +#define free_irq sys_free_irq #endif + +int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { - struct irqaction *old, **p, *action; - unsigned long flags; + struct irqaction *action; + int retval; if (irq >= NR_IRQS) return -EINVAL; if (!handler) - { - /* Free */ - p = &irq_desc[irq].action; - while ((action = *p) != NULL && action->dev_id != dev_id) - p = &action->next; - if (action == NULL) - return -ENOENT; - - /* Found it - now free it */ - save_flags(flags); - cli(); - *p = action->next; - if (irq_desc[irq].action == NULL) - disable_irq(irq); - restore_flags(flags); - irq_kfree(action); - return 0; - } + /* We could implement really free_irq() instead of that... */ + return do_free_irq(irq, dev_id); action = (struct irqaction *) irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) + if (!action) { + printk(KERN_ERR "irq_kmalloc() failed for irq %d !\n", irq); return -ENOMEM; - - save_flags(flags); - cli(); + } action->handler = handler; action->flags = irqflags; @@ -168,57 +255,109 @@ action->name = devname; action->dev_id = dev_id; action->next = NULL; - enable_irq(irq); - - p = &irq_desc[irq].action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & action->flags & SA_SHIRQ)) - return -EBUSY; - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - } - *p = action; - - restore_flags(flags); + retval = setup_irq(irq, action); + if (retval) + kfree(action); + return 0; } -#ifdef CONFIG_APUS -void sys_free_irq(unsigned int irq, void *dev_id) -{ - sys_request_irq(irq, NULL, 0, NULL, dev_id); -} -#else void free_irq(unsigned int irq, void *dev_id) { -#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) - request_8xxirq(irq, NULL, 0, NULL, dev_id); -#else request_irq(irq, NULL, 0, NULL, dev_id); -#endif } -#endif -/* XXX should implement irq disable depth like on intel */ -void disable_irq_nosync(unsigned int irq_nr) +/* + * Generic enable/disable code: this just calls + * down into the PIC-specific version for the actual + * hardware disable after having gotten the irq + * controller lock. + */ + +/** + * disable_irq_nosync - disable an irq without waiting + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. Unlike disable_irq(), this function does not ensure existing + * instances of the IRQ handler have completed before returning. + * + * This function may be called from IRQ context. + */ + + void disable_irq_nosync(unsigned int irq) { - mask_irq(irq_nr); + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + if (!(desc->status & IRQ_PER_CPU)) + desc->status |= IRQ_DISABLED; + mask_irq(irq); + } + spin_unlock_irqrestore(&desc->lock, flags); } -void disable_irq(unsigned int irq_nr) +/** + * disable_irq - disable an irq and wait for completion + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. That is for two disables you need two enables. This + * function waits for any pending IRQ handlers for this interrupt + * to complete before returning. If you use this function while + * holding a resource the IRQ handler may need you will deadlock. + * + * This function may be called - with care - from IRQ context. + */ + +void disable_irq(unsigned int irq) { - mask_irq(irq_nr); - synchronize_irq(); + disable_irq_nosync(irq); + + if (!local_irq_count(smp_processor_id())) { + do { + barrier(); + } while (irq_desc[irq].status & IRQ_INPROGRESS); + } } -void enable_irq(unsigned int irq_nr) +/** + * enable_irq - enable interrupt handling on an irq + * @irq: Interrupt to enable + * + * Re-enables the processing of interrupts on this IRQ line + * providing no disable_irq calls are now in effect. + * + * This function may be called from IRQ context. + */ + +void enable_irq(unsigned int irq) { - unmask_irq(irq_nr); + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { + case 1: { + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + unmask_irq(irq); + /* fall-through */ + } + default: + desc->depth--; + break; + case 0: + printk("enable_irq(%u) unbalanced\n", irq); + } + spin_unlock_irqrestore(&desc->lock, flags); } int get_irq_list(char *buf) @@ -257,15 +396,41 @@ } len += sprintf(buf+len, "\n"); } +#ifdef CONFIG_TAU + len += sprintf(buf+len, "TAU: "); + for (j = 0; j < smp_num_cpus; j++) + len += sprintf(buf+len, "%10u ", + tau_interrupts(j)); + len += sprintf(buf+len, "\n"); +#endif #ifdef CONFIG_SMP /* should this be per processor send/receive? */ - len += sprintf(buf+len, "IPI: %10lu\n", ipi_count); + len += sprintf(buf+len, "IPI (recv/sent): %10u/%u\n", + atomic_read(&ipi_recv), atomic_read(&ipi_sent)); #endif len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts); return len; #endif /* CONFIG_APUS */ } +static inline void +handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action) +{ + int status = 0; + + if (!(action->flags & SA_INTERRUPT)) + __sti(); + + do { + status |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); +} + /* * Eventually, this should take an array of interrupts and an array size * so it can dispatch multiple interrupts. @@ -275,33 +440,80 @@ int status; struct irqaction *action; int cpu = smp_processor_id(); + irq_desc_t *desc = irq_desc + irq; - mask_and_ack_irq(irq); - status = 0; - action = irq_desc[irq].action; kstat.irqs[cpu][irq]++; - if (action && action->handler) { - if (!(action->flags & SA_INTERRUPT)) - __sti(); - do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while ( action ); - __cli(); - if (irq_desc[irq].handler) { - if (irq_desc[irq].handler->end) - irq_desc[irq].handler->end(irq); - else if (irq_desc[irq].handler->enable) - irq_desc[irq].handler->enable(irq); - } - } else { - ppc_spurious_interrupts++; - printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); - disable_irq(irq); + spin_lock(&desc->lock); + ack_irq(irq); + /* + REPLAY is when Linux resends an IRQ that was dropped earlier + WAITING is used by probe to mark irqs that are being tested + */ + status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); + if (!(status & IRQ_PER_CPU)) + status |= IRQ_PENDING; /* we _want_ to handle it */ + + /* + * If the IRQ is disabled for whatever reason, we cannot + * use the action we have. + */ + action = NULL; + if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + action = desc->action; + if (!action || !action->handler) { + ppc_spurious_interrupts++; + printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); + disable_irq(irq); + goto out; + } + status &= ~IRQ_PENDING; /* we commit to handling */ + if (!(status & IRQ_PER_CPU)) + status |= IRQ_INPROGRESS; /* we are handling it */ + } + desc->status = status; + + /* + * If there is no IRQ handler or it was disabled, exit early. + Since we set PENDING, if another processor is handling + a different instance of this same irq, the other processor + will take care of it. + */ + if (!action) + goto out; + + + /* + * Edge triggered interrupts need to remember + * pending events. + * This applies to any hw interrupts that allow a second + * instance of the same irq to arrive while we are in do_IRQ + * or in the handler. But the code here only handles the _second_ + * instance of the irq, not the third or fourth. So it is mostly + * useful for irq hardware that does not mask cleanly in an + * SMP environment. + */ + for (;;) { + spin_unlock(&desc->lock); + handle_irq_event(irq, regs, action); + spin_lock(&desc->lock); + + if (!(desc->status & IRQ_PENDING)) + break; + desc->status &= ~IRQ_PENDING; + } + desc->status &= ~IRQ_INPROGRESS; +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + if (irq_desc[irq].handler) { if (irq_desc[irq].handler->end) irq_desc[irq].handler->end(irq); + else if (irq_desc[irq].handler->enable) + irq_desc[irq].handler->enable(irq); } + spin_unlock(&desc->lock); } int do_IRQ(struct pt_regs *regs, int isfake) @@ -320,6 +532,7 @@ { printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", irq, regs->nip); + /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; } goto out; @@ -362,7 +575,7 @@ #ifdef CONFIG_SMP unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile int global_irq_lock; +unsigned volatile long global_irq_lock; /* pendantic :long for set_bit--RR*/ atomic_t global_irq_count; atomic_t global_bh_count; @@ -694,6 +907,7 @@ err = parse_hex_value(buffer, count, &new_value); +/* Why is this disabled ? --BenH */ #if 0/*CONFIG_SMP*/ /* * Do not allow disabling IRQs completely - it's a too easy diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/local_irq.h linux.ac/arch/ppc/kernel/local_irq.h --- linux-2.4.0/arch/ppc/kernel/local_irq.h Sat Aug 5 00:15:37 2000 +++ linux.ac/arch/ppc/kernel/local_irq.h Wed Jan 3 17:09:05 2001 @@ -15,8 +15,5 @@ extern int ppc_spurious_interrupts; extern int ppc_second_irq; extern struct irqaction *ppc_irq_action[NR_IRQS]; -extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; -extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; -extern atomic_t ppc_n_lost_interrupts; #endif /* _PPC_KERNEL_LOCAL_IRQ_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/m8260_setup.c linux.ac/arch/ppc/kernel/m8260_setup.c --- linux-2.4.0/arch/ppc/kernel/m8260_setup.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/m8260_setup.c Wed Jan 3 17:09:05 2001 @@ -286,10 +286,7 @@ ppc_ide_md.outsw = m8xx_ide_outsw; ppc_ide_md.default_irq = m8xx_ide_default_irq; ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.check_region = m8xx_ide_check_region; - ppc_ide_md.request_region = m8xx_ide_request_region; - ppc_ide_md.release_region = m8xx_ide_release_region; - ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid; + ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; ppc_ide_md.ide_request_irq = m8xx_ide_request_irq; @@ -297,13 +294,39 @@ #endif } -void +/* + * Copied from prom.c so I don't have include all of that crap. + * -- Dan + * + * prom_init() is called very early on, before the kernel text + * and data have been mapped to KERNELBASE. At this point the code + * is running at whatever address it has been loaded at, so + * references to extern and static variables must be relocated + * explicitly. The procedure reloc_offset() returns the address + * we're currently running at minus the address we were linked at. + * (Note that strings count as static variables.) + */ +extern unsigned long reloc_offset(void); +#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) + +__init +unsigned long prom_init(uint r3, uint r4, uint r5, uint r6) { - /* Nothing to do now, but we are called immediatedly upon - * kernel start up with MMU disabled, so if there is - * anything we need to do...... - */ + unsigned long offset = reloc_offset(); + unsigned long phys; + extern char __bss_start, _end; + + /* First zero the BSS -- use memset, some arches don't have + * caches on yet */ + memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); + + /* Default */ + phys = offset + KERNELBASE; + + /* We are done. + */ + return phys; } /* Mainly for ksyms. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/m8xx_setup.c linux.ac/arch/ppc/kernel/m8xx_setup.c --- linux-2.4.0/arch/ppc/kernel/m8xx_setup.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/m8xx_setup.c Wed Jan 3 17:09:12 2001 @@ -344,25 +344,6 @@ } int -m8xx_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return 0; -} - -void -m8xx_ide_request_region(ide_ioreg_t from, - unsigned int extent, - const char *name) -{ -} - -void -m8xx_ide_release_region(ide_ioreg_t from, - unsigned int extent) -{ -} - -int m8xx_ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, @@ -376,12 +357,6 @@ #endif } -void -m8xx_ide_fix_driveid(struct hd_driveid *id) -{ - ppc_generic_ide_fix_driveid(id); -} - /* We can use an external IDE controller or wire the IDE interface to * the internal PCMCIA controller. */ @@ -515,10 +490,7 @@ ppc_ide_md.outsw = m8xx_ide_outsw; ppc_ide_md.default_irq = m8xx_ide_default_irq; ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.check_region = m8xx_ide_check_region; - ppc_ide_md.request_region = m8xx_ide_request_region; - ppc_ide_md.release_region = m8xx_ide_release_region; - ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid; + ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; ppc_ide_md.ide_request_irq = m8xx_ide_request_irq; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/misc.S linux.ac/arch/ppc/kernel/misc.S --- linux-2.4.0/arch/ppc/kernel/misc.S Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/kernel/misc.S Mon Dec 18 20:44:15 2000 @@ -37,6 +37,14 @@ .text + .align 5 +_GLOBAL(__delay) + cmpwi 0,r3,0 + mtctr r3 + beqlr +1: bdnz 1b + blr + /* * Returns (address we're running at) - (address we were linked at) * for use before the text and data are mapped to KERNELBASE. @@ -82,16 +90,16 @@ lwz r7,ppc_n_lost_interrupts@l(r7) cmpi 0,r7,0 /* lost interrupts to process first? */ bne- do_lost_interrupts -1: sync +1: SYNC mtmsr r3 - isync + SYNC blr _GLOBAL(__no_use_cli) mfmsr r0 /* Get current interrupt state */ rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ - sync /* Some chip revs have problems here... */ + SYNC /* Some chip revs have problems here... */ mtmsr r0 /* Update machine state */ blr /* Done */ @@ -102,7 +110,7 @@ ori r3,r3,MSR_EE /* Turn on 'EE' bit */ cmpi 0,r4,0 /* lost interrupts to process first? */ bne- do_lost_interrupts - sync /* Some chip revs have problems here... */ + SYNC /* Some chip revs have problems here... */ mtmsr r3 /* Update machine state */ blr @@ -121,7 +129,7 @@ cmpi 0,r4,0 bne- 1b lwz r3,8(r1) - sync + SYNC mtmsr r3 lwz r0,20(r1) mtlr r0 @@ -137,8 +145,9 @@ mfmsr r0 /* Get current msr */ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */ or r0,r0,r4 /* Or on the bits in r4 (second parm) */ - sync /* Some chip revs have problems here... */ + SYNC /* Some chip revs have problems here... */ mtmsr r0 /* Update machine state */ + isync blr /* Done */ @@ -148,7 +157,7 @@ _GLOBAL(_tlbia) #if defined(CONFIG_SMP) mfmsr r10 - sync + SYNC rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ mtmsr r0 SYNC @@ -161,7 +170,6 @@ bne- 10b stwcx. r8,0,r9 bne- 10b - eieio #endif /* CONFIG_SMP */ sync tlbia @@ -182,7 +190,7 @@ _GLOBAL(_tlbie) #if defined(CONFIG_SMP) mfmsr r10 - sync + SYNC rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ mtmsr r0 SYNC @@ -228,7 +236,7 @@ ori r3,r3,HID0_ICFI mtspr HID0,r3 #endif /* CONFIG_8xx */ - SYNC + isync blr /* @@ -259,7 +267,6 @@ 2: icbi 0,r6 addi r6,r6,CACHE_LINE_SIZE bdnz 2b - sync isync blr @@ -717,6 +724,8 @@ mr r3,r1 /* Close enough */ blr +#if 0 +/* isn't it just easier to use the mtspr/mfspr inline macros?? --Troy */ _GLOBAL(_get_THRM1) mfspr r3,THRM1 blr @@ -740,6 +749,7 @@ _GLOBAL(_set_THRM3) mtspr THRM3,r3 blr +#endif _GLOBAL(_get_PVR) mfspr r3,PVR @@ -755,6 +765,12 @@ mfspr r3,HID0 blr +_GLOBAL(_set_HID0) + sync + mtspr HID0, r3 + SYNC /* Handle erratas in some cases */ + blr + _GLOBAL(_get_ICTC) mfspr r3,ICTC blr @@ -763,7 +779,6 @@ mtspr ICTC,r3 blr - /* L2CR functions Copyright © 1997-1998 by PowerLogix R & D, Inc. @@ -785,6 +800,17 @@ /* Thur, Dec. 12, 1998. - First public release, contributed by PowerLogix. + *********** + Sat, Aug. 7, 1999. + - Terry: Made sure code disabled interrupts before running. (Previously + it was assumed interrupts were already disabled). + - Terry: Updated for tentative G4 support. 4MB of memory is now flushed + instead of 2MB. (Prob. only 3 is necessary). + - Terry: Updated for workaround to HID0[DPM] processor bug + during global invalidates. + *********** + Thu, July 13, 2000. + - Terry: Added isync to correct for an errata. Author: Terry Greeniaus (tgree@phys.ualberta.ca) Please e-mail updates to this file to me, thanks! @@ -823,82 +849,94 @@ causes cache pushes from the L1 cache to go to the L2 cache instead of to main memory. */ - +/* + * Summary: this procedure ignores the L2I bit in the value passed in, + * flushes the cache if it was already enabled, always invalidates the + * cache, then enables the cache if the L2E bit is set in the value + * passed in. + * -- paulus. + */ _GLOBAL(_set_L2CR) - /* Make sure this is a 750 chip */ + /* Make sure this is a 750 or 7400 chip */ mfspr r4,PVR rlwinm r4,r4,16,16,31 - cmplwi r4,0x0008 - beq thisIs750 - cmplwi r4,0x000c - beq thisIs750 - li r3,-1 - blr - -thisIs750: - /* Get the current enable bit of the L2CR into r4 */ - mfspr r4,L2CR - mfmsr r7 - - /* See if we want to perform a global inval this time. */ - rlwinm r6,r3,0,10,10 /* r6 contains the new invalidate bit */ - rlwinm. r5,r3,0,0,0 /* r5 contains the new enable bit */ - rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ - rlwimi r3,r4,0,0,0 /* Keep the enable bit the same as it was. */ - bne dontDisableCache /* Only disable the cache if L2CRApply - has the enable bit off */ - -disableCache: - /* Disable the cache. First, we turn off interrupts. - An interrupt while we are flushing the cache could bring - in data which may not get properly flushed. */ - rlwinm r4,r7,0,17,15 /* Turn off EE bit */ + cmpwi r4,0x0008 + cmpwi cr1,r4,0x000c + cror 2,2,4*cr1+2 + bne 99f + + /* Turn off interrupts and data relocation. */ + mfmsr r7 /* Save MSR in r7 */ + rlwinm r4,r7,0,17,15 + rlwinm r4,r4,0,28,26 /* Turn off DR bit */ sync mtmsr r4 - sync + isync + + /* Get the current enable bit of the L2CR into r4 */ + mfspr r4,L2CR -/* - Now, read the first 2MB of memory to put new data in the cache. - (Actually we only need the size of the L2 cache plus the size - of the L1 cache, but 2MB will cover everything just to be safe). -*/ - lis r4,0x0001 + /* Tweak some bits */ + rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ + + /* Check to see if we need to flush */ + rlwinm. r4,r4,0,0,0 + beq 2f + + /* Flush the cache. First, read the first 4MB of memory (physical) to + * put new data in the cache. (Actually we only need + * the size of the L2 cache plus the size of the L1 cache, but 4MB will + * cover everything just to be safe). + */ + + /**** Might be a good idea to set L2DO here - to prevent instructions + from getting into the cache. But since we invalidate + the next time we enable the cache it doesn't really matter. + ****/ + + lis r4,0x0002 mtctr r4 - lis r4,KERNELBASE@h -1: lwzx r0,r0,r4 - addi r4,r4,0x0020 /* Go to start of next cache line */ + li r4,0 +1: + lwzx r0,r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ bdnz 1b - /* Now, flush the first 2MB of memory */ - lis r4,0x0001 + /* Now, flush the first 4MB of memory */ + lis r4,0x0002 mtctr r4 - lis r4,KERNELBASE@h + li r4,0 sync -2: dcbf r0,r4 - addi r4,r4,0x0020 /* Go to start of next cache line */ - bdnz 2b - - /* Turn off the L2CR enable bit. */ - rlwinm r3,r3,0,1,31 - -dontDisableCache: - /* Set up the L2CR configuration bits */ +1: + dcbf r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + +2: + /* Set up the L2CR configuration bits (and switch L2 off) */ sync mtspr L2CR,r3 sync - /* Reenable interrupts if necessary. */ - mtmsr r7 + /* Before we perform the global invalidation, we must disable dynamic + * power management via HID0[DPM] to work around a processor bug where + * DPM can possibly interfere with the state machine in the processor + * that invalidates the L2 cache tags. + */ + mfspr r8,HID0 /* Save HID0 in r8 */ + rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ sync - - cmplwi r6,0 - beq noInval - + mtspr HID0,r4 /* Disable DPM */ + sync + /* Perform a global invalidation */ oris r3,r3,0x0020 sync mtspr L2CR,r3 sync + isync /* For errata */ /* Wait for the invalidation to complete */ 3: mfspr r3,L2CR @@ -910,27 +948,38 @@ mtspr L2CR,r3 sync -noInval: + /* Restore HID0[DPM] to whatever it was before */ + sync + mtspr 1008,r8 + sync + /* See if we need to enable the cache */ cmplwi r5,0 - beqlr + beq 4f /* Enable the cache */ oris r3,r3,0x8000 mtspr L2CR,r3 sync + + /* Restore MSR (restores EE and DR bits to original state) */ +4: SYNC + mtmsr r7 + isync + blr + +99: li r3,-1 blr _GLOBAL(_get_L2CR) /* Make sure this is a 750 chip */ mfspr r3,PVR - rlwinm r3,r3,16,16,31 - cmplwi r3,0x0008 - beq 1f - cmplwi r3,0x000c + srwi r3,r3,16 + cmpwi r3,0x0008 + cmpwi cr1,r3,0x000c li r3,0 + cror 2,2,4*cr1+2 bnelr -1: /* Return the L2CR contents */ mfspr r3,L2CR blr @@ -986,15 +1035,6 @@ blr #endif -_GLOBAL(__clear_msr_me) - mfmsr r0 /* Get current interrupt state */ - lis r3,0 - ori r3,r3,MSR_ME - andc r0,r0,r3 /* Clears bit in (r4) */ - sync /* Some chip revs have problems here */ - mtmsr r0 /* Update machine state */ - blr - /* * Create a kernel thread * kernel_thread(fn, arg, flags) @@ -1244,16 +1284,20 @@ .long sys_getrlimit /* 190 */ .long sys_ni_syscall /* 191 */ /* Unused */ .long sys_ni_syscall /* 192 - reserved - mmap2 */ - .long sys_ni_syscall /* 193 - reserved - truncate64 */ - .long sys_ni_syscall /* 194 - reserved - ftruncate64 */ - .long sys_ni_syscall /* 195 - reserved - stat64 */ - .long sys_ni_syscall /* 196 - reserved - lstat64 */ - .long sys_ni_syscall /* 197 - reserved - fstat64 */ + .long sys_truncate64 /* 193 */ + .long sys_ftruncate64 /* 194 */ + .long sys_stat64 /* 195 */ + .long sys_lstat64 /* 196 */ + .long sys_fstat64 /* 197 */ .long sys_pciconfig_read /* 198 */ .long sys_pciconfig_write /* 199 */ .long sys_pciconfig_iobase /* 200 */ .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */ .long sys_getdents64 /* 202 */ + .long sys_pivot_root /* 203 */ + .long sys_fcntl64 /* 204 */ + .long sys_madvise /* 205 */ + .long sys_mincore /* 206 */ .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall .endr diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/open_pic.c linux.ac/arch/ppc/kernel/open_pic.c --- linux-2.4.0/arch/ppc/kernel/open_pic.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/open_pic.c Wed Jan 3 17:09:30 2001 @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/openpic.c -- OpenPIC Interrupt Handling + * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling * * Copyright (C) 1997 Geert Uytterhoeven * @@ -13,35 +13,36 @@ #include #include #include -#include +#include #include #include #include #include #include + #include "local_irq.h" +#include "open_pic.h" +#include "open_pic_defs.h" -volatile struct OpenPIC *OpenPIC = NULL; +void* OpenPIC_Addr; +static volatile struct OpenPIC *OpenPIC = NULL; u_int OpenPIC_NumInitSenses __initdata = 0; u_char *OpenPIC_InitSenses __initdata = NULL; -int open_pic_irq_offset; extern int use_of_interrupt_tree; -void chrp_mask_irq(unsigned int); -void chrp_unmask_irq(unsigned int); void find_ISUs(void); static u_int NumProcessors; static u_int NumSources; -OpenPIC_Source *ISU; -/* - * We should use this if we have > 1 ISU. - * We can just point each entry to the - * appropriate source regs but it wastes a lot of space - * so until we have >1 ISU I'll leave it unimplemented. - * -- Cort -OpenPIC_Source ISU[128]; -*/ +static int NumISUs; +static int open_pic_irq_offset; +static volatile unsigned char* chrp_int_ack_special; + +OpenPIC_SourcePtr ISU[OPENPIC_MAX_ISU]; + +static void openpic_end_irq(unsigned int irq_nr); +static void openpic_ack_irq(unsigned int irq_nr); +static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask); struct hw_interrupt_type open_pic = { " OpenPIC ", @@ -49,45 +50,69 @@ NULL, openpic_enable_irq, openpic_disable_irq, - 0, + openpic_ack_irq, + openpic_end_irq, + openpic_set_affinity +}; + +#ifdef CONFIG_SMP +static void openpic_end_ipi(unsigned int irq_nr); +static void openpic_ack_ipi(unsigned int irq_nr); +static void openpic_enable_ipi(unsigned int irq_nr); +static void openpic_disable_ipi(unsigned int irq_nr); + +struct hw_interrupt_type open_pic_ipi = { + " OpenPIC ", + NULL, + NULL, + openpic_enable_ipi, + openpic_disable_ipi, + openpic_ack_ipi, + openpic_end_ipi, 0 }; +#endif /* CONFIG_SMP */ /* - * Accesses to the current processor's registers + * Accesses to the current processor's openpic registers */ -#ifndef __powerpc__ -#define THIS_CPU Private -#define CHECK_THIS_CPU do {} while (0) -#else +#ifdef CONFIG_SMP #define THIS_CPU Processor[cpu] +#define DECL_THIS_CPU int cpu = smp_hw_index[smp_processor_id()] #define CHECK_THIS_CPU check_arg_cpu(cpu) -#endif +#else +#define THIS_CPU Processor[0] +#define DECL_THIS_CPU +#define CHECK_THIS_CPU +#endif /* CONFIG_SMP */ #if 1 #define check_arg_ipi(ipi) \ if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \ - printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi); + printk("open_pic.c:%d: illegal ipi %d\n", __LINE__, ipi); #define check_arg_timer(timer) \ if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \ - printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer); + printk("open_pic.c:%d: illegal timer %d\n", __LINE__, timer); #define check_arg_vec(vec) \ if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \ - printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec); + printk("open_pic.c:%d: illegal vector %d\n", __LINE__, vec); #define check_arg_pri(pri) \ if (pri < 0 || pri >= OPENPIC_NUM_PRI) \ - printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri); + printk("open_pic.c:%d: illegal priority %d\n", __LINE__, pri); /* - * I changed this to return to keep us from from trying to use irq #'s - * that we're using for IPI's. - * -- Cort - */ + * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's + * data has probably been corrupted and we're going to panic or deadlock later + * anyway --Troy + */ +extern unsigned long* _get_SP(void); #define check_arg_irq(irq) \ - /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \ - printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/ + if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \ + printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \ + print_backtrace(_get_SP()); } #define check_arg_cpu(cpu) \ - if (cpu < 0 || cpu >= NumProcessors) \ - printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu); + if (cpu < 0 || cpu >= NumProcessors){ \ + printk("open_pic.c:%d: illegal cpu %d\n", __LINE__, cpu); \ + print_backtrace(_get_SP()); } #else #define check_arg_ipi(ipi) do {} while (0) #define check_arg_timer(timer) do {} while (0) @@ -97,23 +122,10 @@ #define check_arg_cpu(cpu) do {} while (0) #endif -#ifdef CONFIG_SMP -void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - smp_message_recv(cpl-OPENPIC_VEC_IPI, regs); -} -#endif /* CONFIG_SMP */ - -#ifdef __i386__ -static inline u_int in_le32(volatile u_int *addr) -{ - return *addr; -} - -static inline void out_le32(volatile u_int *addr, u_int val) -{ - *addr = val; -} +#ifdef CONFIG_POWER3 + #define GET_ISU(source) ISU[(source) >> 4][(source) & 0xf] +#else + #define GET_ISU(source) ISU[0][(source)] #endif u_int openpic_read(volatile u_int *addr) @@ -156,22 +168,22 @@ u_int field) { openpic_setfield(addr, OPENPIC_MASK); - /* wait until it's not in use */ - /* BenH: Is this code really enough ? I would rather check the result - * and eventually retry ... - */ while (openpic_read(addr) & OPENPIC_ACTIVITY); openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK); } -void __init openpic_init(int main_pic) +void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack, + int programmer_switch_irq) { u_int t, i; u_int timerfreq; const char *version; - if (!OpenPIC) - panic("No OpenPIC found"); + if (!OpenPIC_Addr) { + printk("No OpenPIC found !\n"); + return; + } + OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr; if ( ppc_md.progress ) ppc_md.progress("openpic enter",0x122); @@ -194,179 +206,180 @@ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1; NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >> OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1; - if ( _machine != _MACH_Pmac ) - { - printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version, - NumProcessors, NumSources, OpenPIC); - timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency); - printk("OpenPIC timer frequency is "); - if (timerfreq) - printk("%d MHz\n", timerfreq>>20); - else - printk("not set\n"); + printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", + version, NumProcessors, NumSources, OpenPIC); + timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency); + if (timerfreq) + printk("OpenPIC timer frequency is %d.%06d MHz\n", + timerfreq / 1000000, timerfreq % 1000000); + + if (!main_pic) + return; + + open_pic_irq_offset = offset; + chrp_int_ack_special = (volatile unsigned char*)chrp_ack; + + /* Initialize timer interrupts */ + if ( ppc_md.progress ) ppc_md.progress("openpic timer",0x3ba); + for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { + /* Disabled, Priority 0 */ + openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset); + /* No processor */ + openpic_maptimer(i, 0); } - - if ( main_pic ) - { - /* Initialize timer interrupts */ - if ( ppc_md.progress ) ppc_md.progress("openpic timer",0x3ba); - for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { - /* Disabled, Priority 0 */ - openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i); - /* No processor */ - openpic_maptimer(i, 0); - } - - /* Initialize IPI interrupts */ - if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb); - for (i = 0; i < OPENPIC_NUM_IPI; i++) { - /* Disabled, Priority 8 */ - openpic_initipi(i, 8, OPENPIC_VEC_IPI+i); - } - find_ISUs(); - if ( _machine != _MACH_Pmac ) - { - /* Initialize external interrupts */ - if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc); - /* SIOint (8259 cascade) is special */ - openpic_initirq(0, 8, open_pic_irq_offset, 1, 1); - openpic_mapirq(0, 1<<0); - for (i = 1; i < NumSources; i++) { - /* Enabled, Priority 8 */ - openpic_initirq(i, 8, open_pic_irq_offset+i, 0, - i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1); - /* Processor 0 */ - openpic_mapirq(i, 1<<0); - } - } - else - { - /* Prevent any interrupt from occuring during initialisation. - * Hum... I believe this is not necessary, Apple does that in - * Darwin's PowerExpress code. - */ - openpic_set_priority(0, 0xf); - - /* First disable all interrupts and map them to CPU 0 */ - for (i = 0; i < NumSources; i++) { - openpic_disable_irq(i); - openpic_mapirq(i, 1<<0); - } - - /* If we use the device tree, then lookup all interrupts and - * initialize them according to sense infos found in the tree - */ - if (use_of_interrupt_tree) { - struct device_node* np = find_all_nodes(); - while(np) { - int j, pri; - pri = strcmp(np->name, "programmer-switch") ? 2 : 7; - for (j=0;jn_intrs;j++) { - openpic_initirq(np->intrs[j].line, - pri, - np->intrs[j].line, - 0, - np->intrs[j].sense); - if (np->intrs[j].sense) - irq_desc[np->intrs[j].line].status = IRQ_LEVEL; - } - np = np->next; - } - } - } - - /* Initialize the spurious interrupt */ - if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd); - openpic_set_spurious(OPENPIC_VEC_SPURIOUS); - if ( !(_machine & (_MACH_gemini|_MACH_Pmac)) ) - { - if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, - "82c59 cascade", NULL)) - printk("Unable to get OpenPIC IRQ 0 for cascade\n"); - } - openpic_set_priority(0, 0); - openpic_disable_8259_pass_through(); + +#ifdef CONFIG_SMP + /* Initialize IPI interrupts */ + if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb); + for (i = 0; i < OPENPIC_NUM_IPI; i++) { + /* Disabled, Priority 10..13 */ + openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset); + /* IPIs are per-CPU */ + irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU; + irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi; + } +#endif + + find_ISUs(); + + /* Initialize external interrupts */ + if (ppc_md.progress) ppc_md.progress("openpic ext",0x3bc); + + openpic_set_priority(0xf); + + /* SIOint (8259 cascade) is special */ + if (offset) { + openpic_initirq(0, 8, offset, 1, 1); + openpic_mapirq(0, 1<<0); + } + + /* Init all external sources */ + for (i = 1; i < NumSources; i++) { + int pri, sense; + + /* the bootloader may have left it enabled (bad !) */ + openpic_disable_irq(i+offset); + + pri = (i == programmer_switch_irq)? 9: 8; + sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1; + if (sense) + irq_desc[i+offset].status = IRQ_LEVEL; + + /* Enabled, Priority 8 or 9 */ + openpic_initirq(i, pri, i+offset, !sense, sense); + /* Processor 0 */ + openpic_mapirq(i, 1<<0); + } + + /* Init descriptors */ + for (i = offset; i < NumSources + offset; i++) + irq_desc[i].handler = &open_pic; + + /* Initialize the spurious interrupt */ + if (ppc_md.progress) ppc_md.progress("openpic spurious",0x3bd); + openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset); + + /* Initialize the cascade */ + if (offset) { + if (request_irq(offset, no_action, SA_INTERRUPT, + "82c59 cascade", NULL)) + printk("Unable to get OpenPIC IRQ 0 for cascade\n"); } - if ( ppc_md.progress ) ppc_md.progress("openpic exit",0x222); + openpic_set_priority(0); + openpic_disable_8259_pass_through(); + + if (ppc_md.progress) ppc_md.progress("openpic exit",0x222); } +#ifdef CONFIG_POWER3 +void openpic_setup_ISU(int isu_num, unsigned long addr) +{ + if (isu_num >= OPENPIC_MAX_ISU) + return; + ISU[isu_num] = (OpenPIC_SourcePtr) ioremap(addr, 0x400); + if (isu_num >= NumISUs) + NumISUs = isu_num + 1; +} +#endif + void find_ISUs(void) { -#ifdef CONFIG_PPC64BRIDGE - /* hardcode this for now since the IBM 260 is the only thing with - * a distributed openpic right now. -- Cort +#ifdef CONFIG_POWER3 + /* Use /interrupt-controller/reg and + * /interrupt-controller/interrupt-ranges from OF device tree + * the ISU array is setup in chrp_pci.c in ibm_add_bridges + * as a result + * -- tgall + */ + + /* basically each ISU is a bus, and this assumes that + * open_pic_isu_count interrupts per bus are possible + * ISU == Interrupt Source */ - ISU = (OpenPIC_Source *)0xfeff7c00; - NumSources = 0x10; + NumSources = NumISUs * 0x10; + #else /* for non-distributed OpenPIC implementations it's in the IDU -- Cort */ - ISU = (OpenPIC_Source *)OpenPIC->Source; + ISU[0] = (OpenPIC_Source *)OpenPIC->Source; #endif } -void openpic_reset(void) +static void openpic_reset(void) { openpic_setfield(&OpenPIC->Global.Global_Configuration0, OPENPIC_CONFIG_RESET); } -void openpic_enable_8259_pass_through(void) +static void openpic_enable_8259_pass_through(void) { openpic_clearfield(&OpenPIC->Global.Global_Configuration0, OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); } -void openpic_disable_8259_pass_through(void) +static void openpic_disable_8259_pass_through(void) { openpic_setfield(&OpenPIC->Global.Global_Configuration0, OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); } -#ifndef __i386__ /* * Find out the current interrupt */ -u_int openpic_irq(u_int cpu) +static u_int openpic_irq(void) { u_int vec; + DECL_THIS_CPU; - check_arg_cpu(cpu); + CHECK_THIS_CPU; vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge, OPENPIC_VECTOR_MASK); return vec; } -#endif -#ifndef __powerpc__ -void openpic_eoi(void) -#else -void openpic_eoi(u_int cpu) -#endif +static void openpic_eoi(void) { - check_arg_cpu(cpu); + DECL_THIS_CPU; + + CHECK_THIS_CPU; openpic_write(&OpenPIC->THIS_CPU.EOI, 0); /* Handle PCI write posting */ (void)openpic_read(&OpenPIC->THIS_CPU.EOI); } -#ifndef __powerpc__ -u_int openpic_get_priority(void) -#else -u_int openpic_get_priority(u_int cpu) -#endif +static u_int openpic_get_priority(void) { + DECL_THIS_CPU; + CHECK_THIS_CPU; return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority, OPENPIC_CURRENT_TASK_PRIORITY_MASK); } -#ifndef __powerpc__ -void openpic_set_priority(u_int pri) -#else -void openpic_set_priority(u_int cpu, u_int pri) -#endif +static void openpic_set_priority(u_int pri) { + DECL_THIS_CPU; + CHECK_THIS_CPU; check_arg_pri(pri); openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority, @@ -376,24 +389,43 @@ /* * Get/set the spurious vector */ -u_int openpic_get_spurious(void) +static u_int openpic_get_spurious(void) { return openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK); } -void openpic_set_spurious(u_int vec) +static void openpic_set_spurious(u_int vec) { check_arg_vec(vec); openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, vec); } +#ifdef CONFIG_SMP +/* + * Convert a cpu mask from logical to physical cpu numbers. + */ +static inline u32 physmask(u32 cpumask) +{ + int i; + u32 mask = 0; + + for (i = 0; i < smp_num_cpus; ++i, cpumask >>= 1) + mask |= (cpumask & 1) << smp_hw_index[i]; + return mask; +} +#else +#define physmask(cpumask) (cpumask) +#endif + void openpic_init_processor(u_int cpumask) { - openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask); + openpic_write(&OpenPIC->Global.Processor_Initialization, + physmask(cpumask)); } +#ifdef CONFIG_SMP /* * Initialize an interprocessor interrupt (and disable it) * @@ -401,9 +433,9 @@ * pri: interrupt source priority * vec: the vector it will produce */ -void openpic_initipi(u_int ipi, u_int pri, u_int vec) +static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec) { - check_arg_timer(ipi); + check_arg_ipi(ipi); check_arg_pri(pri); check_arg_vec(vec); openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi), @@ -413,23 +445,43 @@ /* * Send an IPI to one or more CPUs + * + * Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI) + * and not a system-wide interrupt number */ -#ifndef __powerpc__ void openpic_cause_IPI(u_int ipi, u_int cpumask) -#else -void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask) -#endif { + DECL_THIS_CPU; + CHECK_THIS_CPU; check_arg_ipi(ipi); - openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask); + openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), + physmask(cpumask)); } -void openpic_enable_IPI(u_int ipi) +void openpic_request_IPIs(void) { - check_arg_ipi(ipi); - openpic_clearfield(&OpenPIC->Global.IPI_Vector_Priority(ipi), - OPENPIC_MASK); + int i; + + /* + * Make sure this matches what is defined in smp.c for + * smp_message_{pass|recv}() or what shows up in + * /proc/interrupts will be wrong!!! --Troy */ + + if (OpenPIC == NULL) + return; + + request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset, + openpic_ipi_action, 0, "IPI0 (call function)", 0); + request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1, + openpic_ipi_action, 0, "IPI1 (reschedule)", 0); + request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2, + openpic_ipi_action, 0, "IPI2 (invalidate tlb)", 0); + request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3, + openpic_ipi_action, 0, "IPI3 (xmon break)", 0); + + for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) + openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i); } /* @@ -437,21 +489,27 @@ * * Get IPI's working and start taking interrupts. * -- Cort - */ -void do_openpic_setup_cpu(void) + */ +static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED; + +void __init do_openpic_setup_cpu(void) { int i; - - for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) - openpic_enable_IPI(i); -#if 0 - /* let the openpic know we want intrs */ - for ( i = 0; i < NumSources ; i++ ) - openpic_mapirq(i, openpic_read(ISU[i].Destination) - | (1<Global.Timer[timer].Destination, cpumask); + openpic_write(&OpenPIC->Global.Timer[timer].Destination, + physmask(cpumask)); } + /* - * Enable/disable an interrupt source + * + * All functions below take an offset'ed irq argument + * */ -void openpic_enable_irq(u_int irq) + + +/* + * Enable/disable an external interrupt source + * + * Externally called, irq is an offseted system-wide interrupt number + */ +static void openpic_enable_irq(u_int irq) { check_arg_irq(irq); - openpic_clearfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_clearfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK); /* make sure mask gets to controller before we return to user */ do { mb(); /* sync is probably useless here */ - } while(openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, + } while(openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK)); } -void openpic_disable_irq(u_int irq) +static void openpic_disable_irq(u_int irq) { + u32 vp; + check_arg_irq(irq); - openpic_setfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_setfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK); /* make sure mask gets to controller before we return to user */ do { mb(); /* sync is probably useless here */ - } while(!openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, - OPENPIC_MASK)); + vp = openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, + OPENPIC_MASK | OPENPIC_ACTIVITY); + } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK)); } +#ifdef CONFIG_SMP +/* + * Enable/disable an IPI interrupt source + * + * Externally called, irq is an offseted system-wide interrupt number + */ +void openpic_enable_ipi(u_int irq) +{ + irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset); + check_arg_ipi(irq); + openpic_clearfield(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK); + /* make sure mask gets to controller before we return to user */ + do { + mb(); /* sync is probably useless here */ + } while(openpic_readfield(&OpenPIC->Global.IPI_Vector_Priority(irq), + OPENPIC_MASK)); +} +void openpic_disable_ipi(u_int irq) +{ + u32 vp; + + irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset); + check_arg_ipi(irq); + openpic_setfield(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK); + /* make sure mask gets to controller before we return to user */ + do { + mb(); /* sync is probably useless here */ + vp = openpic_readfield(&OpenPIC->Global.IPI_Vector_Priority(irq), + OPENPIC_MASK | OPENPIC_ACTIVITY); + } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK)); +} +#endif + /* * Initialize an interrupt source (and disable it!) * @@ -513,12 +618,9 @@ * pol: polarity (1 for positive, 0 for negative) * sense: 1 for level, 0 for edge */ -void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense) +static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense) { - check_arg_irq(irq); - check_arg_pri(pri); - check_arg_vec(vec); - openpic_safe_writefield(&ISU[irq].Vector_Priority, + openpic_safe_writefield(&GET_ISU(irq).Vector_Priority, OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK, (pri << OPENPIC_PRIORITY_SHIFT) | vec | @@ -530,10 +632,9 @@ /* * Map an interrupt source to one or more CPUs */ -void openpic_mapirq(u_int irq, u_int cpumask) +static void openpic_mapirq(u_int irq, u_int physmask) { - check_arg_irq(irq); - openpic_write(&ISU[irq].Destination, cpumask); + openpic_write(&GET_ISU(irq).Destination, physmask); } /* @@ -541,10 +642,95 @@ * * sense: 1 for level, 0 for edge */ -void openpic_set_sense(u_int irq, int sense) +static void openpic_set_sense(u_int irq, int sense) { - check_arg_irq(irq); - openpic_safe_writefield(&ISU[irq].Vector_Priority, + openpic_safe_writefield(&GET_ISU(irq).Vector_Priority, OPENPIC_SENSE_LEVEL, (sense ? OPENPIC_SENSE_LEVEL : 0)); } + +/* No spinlocks, should not be necessary with the OpenPIC + * (1 register = 1 interrupt and we have the desc lock). + */ +static void openpic_ack_irq(unsigned int irq_nr) +{ +#if 1 /* masking should be unnecessary, but I still get spurrious */ + openpic_disable_irq(irq_nr); +#endif + if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) + openpic_eoi(); +} + +static void openpic_end_irq(unsigned int irq_nr) +{ + if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0) + openpic_eoi(); + +#if 1 /* masking should be unnecessary, but I still get spurrious */ + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + openpic_enable_irq(irq_nr); +#endif +} + +static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask) +{ + openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask)); +} + +#ifdef CONFIG_SMP +static void openpic_ack_ipi(unsigned int irq_nr) +{ +} + +static void openpic_end_ipi(unsigned int irq_nr) +{ + /* IPIs are marked IRQ_PER_CPU. This has the side effect of + * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from + * applying to them. We EOI them late to avoid re-entering. + * however, I'm wondering if we could simply let them have the + * SA_INTERRUPT flag and let them execute with all interrupts OFF. + * This would have the side effect of either running cross-CPU + * functions with interrupts off, or we can re-enable them explicitely + * with a __sti() in smp_call_function_interrupt(), since + * smp_call_function() is protected by a spinlock. + * Or maybe we shouldn't set the IRQ_PER_CPU flag on cross-CPU + * function calls IPI at all but that would make a special case. + */ + openpic_eoi(); +} + +static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset, regs); +} + +#endif /* CONFIG_SMP */ + +/* This one may be merged with PReP and CHRP */ +int +openpic_get_irq(struct pt_regs *regs) +{ + extern int i8259_irq(int cpu); + + int irq = openpic_irq(); + + /* Management of the cascade should be moved out of here */ + if (open_pic_irq_offset && irq == open_pic_irq_offset) + { + /* + * This magic address generates a PCI IACK cycle. + */ + if ( chrp_int_ack_special ) + irq = *chrp_int_ack_special; + else + irq = i8259_irq( smp_processor_id() ); + openpic_eoi(); + } + if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) { + irq = -1; + /* That's not SMP safe ... but who cares ? */ + ppc_spurious_interrupts++; + } + return irq; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/open_pic.h linux.ac/arch/ppc/kernel/open_pic.h --- linux-2.4.0/arch/ppc/kernel/open_pic.h Tue Jan 11 02:25:06 2000 +++ linux.ac/arch/ppc/kernel/open_pic.h Wed Jan 3 17:09:30 2001 @@ -1,11 +1,43 @@ +/* + * arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + */ + #ifndef _PPC_KERNEL_OPEN_PIC_H #define _PPC_KERNEL_OPEN_PIC_H +#define OPENPIC_SIZE 0x40000 + +/* OpenPIC IRQ controller structure */ extern struct hw_interrupt_type open_pic; -void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); -void openpic_enable_IPI(u_int ipi); -void do_openpic_setup_cpu(void); +/* OpenPIC IPI controller structure */ +#ifdef CONFIG_SMP +extern struct hw_interrupt_type open_pic_ipi; +#endif /* CONFIG_SMP */ + +extern u_int OpenPIC_NumInitSenses; +extern u_char *OpenPIC_InitSenses; +extern void* OpenPIC_Addr; + +/* Exported functions */ +extern void openpic_init(int, int, unsigned char *, int); +extern void openpic_request_IPIs(void); +extern void do_openpic_setup_cpu(void); +extern int openpic_get_irq(struct pt_regs *regs); +extern void openpic_init_processor(u_int cpumask); +extern void openpic_setup_ISU(int isu_num, unsigned long addr); +extern void openpic_cause_IPI(u_int ipi, u_int cpumask); -extern int open_pic_irq_offset; +extern inline int openpic_to_irq(int irq) +{ + return irq += NUM_8259_INTERRUPTS; +} +/*extern int open_pic_irq_offset;*/ #endif /* _PPC_KERNEL_OPEN_PIC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/open_pic_defs.h linux.ac/arch/ppc/kernel/open_pic_defs.h --- linux-2.4.0/arch/ppc/kernel/open_pic_defs.h Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/kernel/open_pic_defs.h Thu Dec 21 21:33:07 2000 @@ -0,0 +1,357 @@ +/* + * linux/openpic.h -- OpenPIC definitions + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This file is based on the following documentation: + * + * The Open Programmable Interrupt Controller (PIC) + * Register Interface Specification Revision 1.2 + * + * Issue Date: October 1995 + * + * Issued jointly by Advanced Micro Devices and Cyrix Corporation + * + * AMD is a registered trademark of Advanced Micro Devices, Inc. + * Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc. + * All Rights Reserved. + * + * To receive a copy of this documentation, send an email to openpic@amd.com. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef _LINUX_OPENPIC_H +#define _LINUX_OPENPIC_H + +#if !defined(__powerpc__) && !defined(__i386__) +#error Unsupported OpenPIC platform +#endif + + +#ifdef __KERNEL__ + +#include + + /* + * OpenPIC supports up to 2048 interrupt sources and up to 32 processors + */ + +#define OPENPIC_MAX_SOURCES 2048 +#define OPENPIC_MAX_PROCESSORS 32 +#define OPENPIC_MAX_ISU 16 + +#define OPENPIC_NUM_TIMERS 4 +#define OPENPIC_NUM_IPI 4 +#define OPENPIC_NUM_PRI 16 +#define OPENPIC_NUM_VECTORS 256 + + + /* + * Non-offset'ed vector numbers + */ + +#define OPENPIC_VEC_TIMER 64 /* and up */ +#define OPENPIC_VEC_IPI 72 /* and up */ +#define OPENPIC_VEC_SPURIOUS 127 + + + /* + * OpenPIC Registers are 32 bits and aligned on 128 bit boundaries + */ + +typedef struct _OpenPIC_Reg { + u_int Reg; /* Little endian! */ + char Pad[0xc]; +} OpenPIC_Reg; + + + /* + * Per Processor Registers + */ + +typedef struct _OpenPIC_Processor { + /* + * Private Shadow Registers (for SLiC backwards compatibility) + */ + u_int IPI0_Dispatch_Shadow; /* Write Only */ + char Pad1[0x4]; + u_int IPI0_Vector_Priority_Shadow; /* Read/Write */ + char Pad2[0x34]; + /* + * Interprocessor Interrupt Command Ports + */ + OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI]; /* Write Only */ + /* + * Current Task Priority Register + */ + OpenPIC_Reg _Current_Task_Priority; /* Read/Write */ +#ifndef __powerpc__ + /* + * Who Am I Register + */ + OpenPIC_Reg _Who_Am_I; /* Read Only */ +#else + char Pad3[0x10]; +#endif +#ifndef __i386__ + /* + * Interrupt Acknowledge Register + */ + OpenPIC_Reg _Interrupt_Acknowledge; /* Read Only */ +#else + char Pad4[0x10]; +#endif + /* + * End of Interrupt (EOI) Register + */ + OpenPIC_Reg _EOI; /* Read/Write */ + char Pad5[0xf40]; +} OpenPIC_Processor; + + + /* + * Timer Registers + */ + +typedef struct _OpenPIC_Timer { + OpenPIC_Reg _Current_Count; /* Read Only */ + OpenPIC_Reg _Base_Count; /* Read/Write */ + OpenPIC_Reg _Vector_Priority; /* Read/Write */ + OpenPIC_Reg _Destination; /* Read/Write */ +} OpenPIC_Timer; + + + /* + * Global Registers + */ + +typedef struct _OpenPIC_Global { + /* + * Feature Reporting Registers + */ + OpenPIC_Reg _Feature_Reporting0; /* Read Only */ + OpenPIC_Reg _Feature_Reporting1; /* Future Expansion */ + /* + * Global Configuration Registers + */ + OpenPIC_Reg _Global_Configuration0; /* Read/Write */ + OpenPIC_Reg _Global_Configuration1; /* Future Expansion */ + /* + * Vendor Specific Registers + */ + OpenPIC_Reg _Vendor_Specific[4]; + /* + * Vendor Identification Register + */ + OpenPIC_Reg _Vendor_Identification; /* Read Only */ + /* + * Processor Initialization Register + */ + OpenPIC_Reg _Processor_Initialization; /* Read/Write */ + /* + * IPI Vector/Priority Registers + */ + OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */ + /* + * Spurious Vector Register + */ + OpenPIC_Reg _Spurious_Vector; /* Read/Write */ + /* + * Global Timer Registers + */ + OpenPIC_Reg _Timer_Frequency; /* Read/Write */ + OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS]; + char Pad1[0xee00]; +} OpenPIC_Global; + + + /* + * Interrupt Source Registers + */ + +typedef struct _OpenPIC_Source { + OpenPIC_Reg _Vector_Priority; /* Read/Write */ + OpenPIC_Reg _Destination; /* Read/Write */ +} OpenPIC_Source, *OpenPIC_SourcePtr; + + + /* + * OpenPIC Register Map + */ + +struct OpenPIC { +#ifndef __powerpc__ + /* + * Per Processor Registers --- Private Access + */ + OpenPIC_Processor Private; +#else + char Pad1[0x1000]; +#endif + /* + * Global Registers + */ + OpenPIC_Global Global; + /* + * Interrupt Source Configuration Registers + */ + OpenPIC_Source Source[OPENPIC_MAX_SOURCES]; + /* + * Per Processor Registers + */ + OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS]; +}; + +extern volatile struct OpenPIC *OpenPIC; + + + /* + * Current Task Priority Register + */ + +#define OPENPIC_CURRENT_TASK_PRIORITY_MASK 0x0000000f + + /* + * Who Am I Register + */ + +#define OPENPIC_WHO_AM_I_ID_MASK 0x0000001f + + /* + * Feature Reporting Register 0 + */ + +#define OPENPIC_FEATURE_LAST_SOURCE_MASK 0x07ff0000 +#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT 16 +#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK 0x00001f00 +#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT 8 +#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff + + /* + * Global Configuration Register 0 + */ + +#define OPENPIC_CONFIG_RESET 0x80000000 +#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE 0x20000000 +#define OPENPIC_CONFIG_BASE_MASK 0x000fffff + + /* + * Vendor Identification Register + */ + +#define OPENPIC_VENDOR_ID_STEPPING_MASK 0x00ff0000 +#define OPENPIC_VENDOR_ID_STEPPING_SHIFT 16 +#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00 +#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT 8 +#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK 0x000000ff + + /* + * Vector/Priority Registers + */ + +#define OPENPIC_MASK 0x80000000 +#define OPENPIC_ACTIVITY 0x40000000 /* Read Only */ +#define OPENPIC_PRIORITY_MASK 0x000f0000 +#define OPENPIC_PRIORITY_SHIFT 16 +#define OPENPIC_VECTOR_MASK 0x000000ff + + + /* + * Interrupt Source Registers + */ + +#define OPENPIC_POLARITY_POSITIVE 0x00800000 +#define OPENPIC_POLARITY_NEGATIVE 0x00000000 +#define OPENPIC_POLARITY_MASK 0x00800000 +#define OPENPIC_SENSE_LEVEL 0x00400000 +#define OPENPIC_SENSE_EDGE 0x00000000 +#define OPENPIC_SENSE_MASK 0x00400000 + + + /* + * Timer Registers + */ + +#define OPENPIC_COUNT_MASK 0x7fffffff +#define OPENPIC_TIMER_TOGGLE 0x80000000 +#define OPENPIC_TIMER_COUNT_INHIBIT 0x80000000 + + + /* + * Aliases to make life simpler + */ + +/* Per Processor Registers */ +#define IPI_Dispatch(i) _IPI_Dispatch[i].Reg +#define Current_Task_Priority _Current_Task_Priority.Reg +#ifndef __powerpc__ +#define Who_Am_I _Who_Am_I.Reg +#endif +#ifndef __i386__ +#define Interrupt_Acknowledge _Interrupt_Acknowledge.Reg +#endif +#define EOI _EOI.Reg + +/* Global Registers */ +#define Feature_Reporting0 _Feature_Reporting0.Reg +#define Feature_Reporting1 _Feature_Reporting1.Reg +#define Global_Configuration0 _Global_Configuration0.Reg +#define Global_Configuration1 _Global_Configuration1.Reg +#define Vendor_Specific(i) _Vendor_Specific[i].Reg +#define Vendor_Identification _Vendor_Identification.Reg +#define Processor_Initialization _Processor_Initialization.Reg +#define IPI_Vector_Priority(i) _IPI_Vector_Priority[i].Reg +#define Spurious_Vector _Spurious_Vector.Reg +#define Timer_Frequency _Timer_Frequency.Reg + +/* Timer Registers */ +#define Current_Count _Current_Count.Reg +#define Base_Count _Base_Count.Reg +#define Vector_Priority _Vector_Priority.Reg +#define Destination _Destination.Reg + +/* Interrupt Source Registers */ +#define Vector_Priority _Vector_Priority.Reg +#define Destination _Destination.Reg + + /* + * Local (static) OpenPIC Operations + */ + + +/* Global Operations */ +static void openpic_reset(void); +static void openpic_enable_8259_pass_through(void); +static void openpic_disable_8259_pass_through(void); +static u_int openpic_irq(void); +static void openpic_eoi(void); +static u_int openpic_get_priority(void); +static void openpic_set_priority(u_int pri); +static u_int openpic_get_spurious(void); +static void openpic_set_spurious(u_int vector); + +/* Interprocessor Interrupts */ +static void openpic_initipi(u_int ipi, u_int pri, u_int vector); + +/* Timer Interrupts */ +static void openpic_inittimer(u_int timer, u_int pri, u_int vector); +static void openpic_maptimer(u_int timer, u_int cpumask); + +/* Interrupt Sources */ +static void openpic_enable_irq(u_int irq); +static void openpic_disable_irq(u_int irq); +static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, + int is_level); +static void openpic_mapirq(u_int irq, u_int cpumask); +static void openpic_set_sense(u_int irq, int sense); + +#ifdef CONFIG_SMP +static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); +#endif + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_OPENPIC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/pci.c linux.ac/arch/ppc/kernel/pci.c --- linux-2.4.0/arch/ppc/kernel/pci.c Tue Nov 7 19:25:00 2000 +++ linux.ac/arch/ppc/kernel/pci.c Wed Jan 3 17:09:30 2001 @@ -8,10 +8,10 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -25,7 +25,7 @@ #include "pci.h" -#undef DEBUG +#define DEBUG #ifdef DEBUG #define DBG(x...) printk(x) @@ -37,54 +37,44 @@ unsigned long isa_mem_base = 0; unsigned long pci_dram_offset = 0; -struct pci_fixup pcibios_fixups[] = { - { 0 } -}; +static u8* pci_to_OF_bus_map; -int generic_pcibios_read_byte(struct pci_dev *dev, int where, u8 *val) -{ - return ppc_md.pcibios_read_config_byte(dev->bus->number,dev->devfn,where,val); -} -int generic_pcibios_read_word(struct pci_dev *dev, int where, u16 *val) -{ - return ppc_md.pcibios_read_config_word(dev->bus->number,dev->devfn,where,val); -} -int generic_pcibios_read_dword(struct pci_dev *dev, int where, u32 *val) -{ - return ppc_md.pcibios_read_config_dword(dev->bus->number,dev->devfn,where,val); -} -int generic_pcibios_write_byte(struct pci_dev *dev, int where, u8 val) -{ - return ppc_md.pcibios_write_config_byte(dev->bus->number,dev->devfn,where,val); -} -int generic_pcibios_write_word(struct pci_dev *dev, int where, u16 val) -{ - return ppc_md.pcibios_write_config_word(dev->bus->number,dev->devfn,where,val); -} -int generic_pcibios_write_dword(struct pci_dev *dev, int where, u32 val) -{ - return ppc_md.pcibios_write_config_dword(dev->bus->number,dev->devfn,where,val); -} +static void pcibios_fixup_resources(struct pci_dev* dev); +#ifdef CONFIG_ALL_PPC +static void pcibios_fixup_cardbus(struct pci_dev* dev); +#endif -struct pci_ops generic_pci_ops = -{ - generic_pcibios_read_byte, - generic_pcibios_read_word, - generic_pcibios_read_dword, - generic_pcibios_write_byte, - generic_pcibios_write_word, - generic_pcibios_write_dword -}; +/* By default, we don't re-assign bus numbers. We do this only on + * some pmacs + */ +int pci_assign_all_busses; +struct pci_controller* hose_head; +struct pci_controller** hose_tail = &hose_head; +static int pci_bus_count; -void pcibios_update_resource(struct pci_dev *dev, struct resource *root, +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources }, +#ifdef CONFIG_ALL_PPC + /* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */ + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211, pcibios_fixup_cardbus }, +#endif /* CONFIG_ALL_PPC */ + { 0 } +}; + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *res, int resource) { u32 new, check; int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + struct pci_controller* hose = dev->sysdata; + + new = res->start; + if (hose && res->flags & IORESOURCE_MEM) + new -= hose->pci_mem_offset; + new |= (res->flags & PCI_REGION_FLAG_MASK); if (resource < 6) { reg = PCI_BASE_ADDRESS_0 + 4*resource; } else if (resource == PCI_ROM_RESOURCE) { @@ -104,6 +94,62 @@ } } +static void +pcibios_fixup_resources(struct pci_dev* dev) +{ + struct pci_controller* hose = + (struct pci_controller *)dev->sysdata; + int i; + if (!hose) { + printk("No hose for PCI dev %x.%x !\n", dev->bus->number, dev->devfn >> 3); + return; + } + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + struct resource *res = dev->resource + i; + if (!res->start) + continue; + if (res->flags & IORESOURCE_MEM) { + res->start += hose->pci_mem_offset; + res->end += hose->pci_mem_offset; +#ifdef DEBUG + printk("Fixup mem res, dev: %x.%x, res_start: %lx->%lx\n", + dev->bus->number, dev->devfn>>3, res->start-hose->pci_mem_offset, + res->start); +#endif + } + + if ((res->flags & IORESOURCE_IO) + && (unsigned long) hose->io_base_virt != isa_io_base) { + unsigned long offs = (unsigned long) hose->io_base_virt - isa_io_base; + res->start += offs; + res->end += offs; + printk("Fixup IO res, dev: %x.%x, res_start: %lx->%lx\n", + dev->bus->number, dev->devfn>>3, + res->start - offs, res->start); + } + } +} + +#ifdef CONFIG_ALL_PPC +static void +pcibios_fixup_cardbus(struct pci_dev* dev) +{ + /* + * Fix the interrupt routing on the TI1211 chip on the 1999 + * G3 powerbook, which doesn't get initialized properly by OF. + */ + if (dev->vendor == PCI_VENDOR_ID_TI + && dev->device == PCI_DEVICE_ID_TI_1211) { + u32 val; + /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA + signal out the MFUNC0 pin */ + if (pci_read_config_dword(dev, 0x8c, &val) == 0 + && val == 0) + pci_write_config_dword(dev, 0x8c, 2); + } +} +#endif /* CONFIG_ALL_PPC */ + /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the @@ -172,7 +218,8 @@ * as well. */ -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) +static void __init +pcibios_allocate_bus_resources(struct list_head *bus_list) { struct list_head *ln; struct pci_bus *bus; @@ -197,7 +244,8 @@ } } -static void __init pcibios_allocate_resources(int pass) +static void __init +pcibios_allocate_resources(int pass) { struct pci_dev *dev; int idx, disabled; @@ -250,7 +298,8 @@ } } -static void __init pcibios_assign_resources(void) +static void __init +pcibios_assign_resources(void) { struct pci_dev *dev; int idx; @@ -278,7 +327,8 @@ * the BIOS forgot to do so or because we have decided the old * address was unusable for some reason. */ - if (!r->start && r->end) + if (!r->start && r->end && ppc_md.pcibios_enable_device_hook && + !ppc_md.pcibios_enable_device_hook(dev, 1)) pci_assign_resource(dev, idx); } @@ -293,7 +343,8 @@ } -int pcibios_enable_resources(struct pci_dev *dev) +int +pcibios_enable_resources(struct pci_dev *dev) { u16 cmd, old_cmd; int idx; @@ -321,18 +372,269 @@ return 0; } +struct pci_controller * __init +pcibios_alloc_controller(void) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); + memset(hose, 0, sizeof(struct pci_controller)); + + *hose_tail = hose; + hose_tail = &hose->next; + + return hose; +} + +static void +make_one_node_map(struct device_node* node, u8 pci_bus) +{ + int *bus_range; + int len; + + if (pci_bus >= pci_bus_count) + return; + bus_range = (int *) get_property(node, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + node->full_name); + return; + } + pci_to_OF_bus_map[pci_bus] = bus_range[0]; + + for (node=node->child; node != 0;node = node->sibling) { + struct pci_dev* dev; + unsigned int *class_code, *reg; + + class_code = (unsigned int *) get_property(node, "class-code", 0); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + reg = (unsigned int *)get_property(node, "reg", 0); + if (!reg) + continue; + dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); + if (!dev || !dev->subordinate) + continue; + make_one_node_map(node, dev->subordinate->number); + } +} + +void +pcibios_make_OF_bus_map(void) +{ + int i; + struct pci_controller* hose; + u8* of_prop_map; + + pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL); + if (!pci_to_OF_bus_map) { + printk(KERN_ERR "Can't allocate OF bus map !\n"); + return; + } + + /* We fill the bus map with invalid values, that helps + * debugging. + */ + for (i=0; inext) { + struct device_node* node; + node = (struct device_node *)hose->arch_data; + if (!node) + continue; + make_one_node_map(node, hose->first_busno); + } + of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", 0); + if (of_prop_map) + memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count); +#ifdef DEBUG + printk("PCI->OF bus map:\n"); + for (i=0; i %d\n", i, pci_to_OF_bus_map[i]); + } +#endif +} + +static struct device_node* +scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) +{ + struct device_node* sub_node; + + for (; node != 0;node = node->sibling) { + unsigned int *class_code, *reg; + + reg = (unsigned int *) get_property(node, "reg", 0); + if (reg && ((reg[0] >> 8) & 0xff) == dev_fn + && ((reg[0] >> 16) & 0xff) == bus) + return node; + + /* For PCI<->PCI bridges or CardBus bridges, we go down */ + class_code = (unsigned int *) get_property(node, "class-code", 0); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn); + if (sub_node) + return sub_node; + } + return NULL; +} +/* + * Scans the OF tree for a device node matching a PCI device + */ +struct device_node* +pci_device_to_OF_node(struct pci_dev *dev) +{ + struct pci_controller *hose; + struct device_node *node; + int bus; + + if (!have_of) + return NULL; + + /* Lookup the hose */ + bus = dev->bus->number; + hose = pci_bus_to_hose(bus); + if (!hose) + return NULL; + + /* Check it has an OF node associated */ + node = (struct device_node *) hose->arch_data; + if (!node) + return NULL; + + /* Fixup bus number according to what OF think it is. */ + if (pci_to_OF_bus_map) + bus = pci_to_OF_bus_map[bus]; + if (bus == 0xff) + return NULL; + + /* Now, lookup childs of the hose */ + return scan_OF_childs_for_device(node->child, bus, dev->devfn); +} + +/* This routine is meant to be used early during boot, when the + * PCI bus numbers have not yet been assigned, and you need to + * issue PCI config cycles to an OF device. + * It could also be used to "fix" RTAS config cycles if you want + * to set pci_assign_all_busses to 1 and still use RTAS for PCI + * config cycles. + */ +struct pci_controller* +pci_find_hose_for_OF_device(struct device_node* node) +{ + if (!have_of) + return NULL; + while(node) { + struct pci_controller* hose; + for (hose=hose_head;hose;hose=hose->next) + if (hose->arch_data == node) + return hose; + node=node->parent; + } + return NULL; +} + +/* + * Returns the PCI device matching a given OF node + */ +int +pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) +{ + unsigned int *reg; + int i; + + if (!have_of) + return -ENODEV; + reg = (unsigned int *) get_property(node, "reg", 0); + if (!reg) + return -ENODEV; + *bus = (reg[0] >> 16) & 0xff; + for (i=0; pci_to_OF_bus_map && i> 8) & 0xff); + return 0; +} -void __init pcibios_init(void) +void __init +pcibios_init(void) { + struct pci_controller *hose; + struct pci_bus *bus; + int next_busno; + printk("PCI: Probing PCI hardware\n"); - pci_scan_bus(0, &generic_pci_ops, NULL); + + /* Scan all of the recorded PCI controllers. */ + for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { + if (pci_assign_all_busses) + hose->first_busno = next_busno; + hose->last_busno = 0xff; + bus = pci_scan_bus(hose->first_busno, hose->ops, hose); + hose->bus = bus; + hose->last_busno = bus->subordinate; + if (pci_assign_all_busses || next_busno <= hose->last_busno) + next_busno = hose->last_busno+1; + } + pci_bus_count = next_busno; + + /* OpenFirmware based machines need a map of OF bus + * numbers vs. kernel bus numbers since we may have to + * remap them. + */ + if (pci_assign_all_busses && have_of) + pcibios_make_OF_bus_map(); + + /* Call machine dependant fixup */ if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); + + /* Allocate and assign resources */ pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); pcibios_assign_resources(); + if (_machine == _MACH_prep) + pci_assign_unassigned_resources(); + +#ifdef CONFIG_BLK_DEV_IDE + /* OF fails to initialize IDE controllers on macs + * (and maybe other machines) + * + * This late fixup is done here since I want it to happen after + * resource assignement, and there's no "late-init" arch hook + * + * Ideally, this should be moved to the IDE layer, but we need + * to check specifically with Andre Hedrick how to do it cleanly + * since the common IDE code seem to care about the fact that the + * BIOS may have disabled a controller. + * + * -- BenH + */ + if (_machine == _MACH_Pmac) { + struct pci_dev *dev; + pci_for_each_dev(dev) + { + if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) + pci_enable_device(dev); + } + } +#endif /* CONFIG_BLK_DEV_IDE */ +} + +int __init +pcibios_assign_all_busses(void) +{ + return pci_assign_all_busses; } void __init @@ -344,9 +646,16 @@ ranges->mem_end -= bus->resource[1]->start; } +unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, + unsigned long start, unsigned long size) +{ + return start; +} void __init pcibios_fixup_bus(struct pci_bus *bus) { + pci_read_bridge_bases(bus); + if ( ppc_md.pcibios_fixup_bus ) ppc_md.pcibios_fixup_bus(bus); } @@ -370,6 +679,10 @@ int idx; struct resource *r; + if (ppc_md.pcibios_enable_device_hook) + if (ppc_md.pcibios_enable_device_hook(dev, 0)) + return -EINVAL; + pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for (idx=0; idx<6; idx++) { @@ -391,37 +704,99 @@ return 0; } -void * -pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical) +struct pci_controller* +pci_bus_to_hose(int bus) { - if (!ppc_md.pci_dev_io_base) { - /* Please, someone fix this for non-pmac machines, we - * need either the virtual or physical PCI IO base - */ - return 0; - } - return ppc_md.pci_dev_io_base(bus, devfn, physical); + struct pci_controller* hose = hose_head; + + for (; hose; hose = hose->next) + if (bus >= hose->first_busno && bus <= hose->last_busno) + return hose; + return NULL; } -void * -pci_dev_mem_base(unsigned char bus, unsigned char devfn) +void* +pci_bus_io_base(unsigned int bus) { - /* Default memory base is 0 (1:1 mapping) */ - if (!ppc_md.pci_dev_mem_base) { - /* Please, someone fix this for non-pmac machines.*/ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return NULL; + return hose->io_base_virt; +} + +unsigned long +pci_bus_io_base_phys(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) return 0; - } - return ppc_md.pci_dev_mem_base(bus, devfn); + return hose->io_base_phys; } -/* Returns the root-bridge number (Uni-N number) of a device */ -int -pci_dev_root_bridge(unsigned char bus, unsigned char devfn) +unsigned long +pci_bus_mem_base_phys(unsigned int bus) { - /* Defaults to 0 */ - if (!ppc_md.pci_dev_root_bridge) + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) return 0; - return ppc_md.pci_dev_root_bridge(bus, devfn); + return hose->pci_mem_offset; +} + +#ifdef CONFIG_POWER4 +extern unsigned long pci_address_offset(int, unsigned int); +#endif /* CONFIG_POWER4 */ + +unsigned long +pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) +{ + /* Hack alert again ! See comments in chrp_pci.c + */ +#ifdef CONFIG_POWER4 + unsigned long offset = pci_address_offset(pdev->bus->number, res->flags); + return res->start - offset; +#else /* CONFIG_POWER4 */ + struct pci_controller* hose = + (struct pci_controller *)pdev->sysdata; + if (hose && res->flags & IORESOURCE_MEM) + return res->start - hose->pci_mem_offset; + /* We may want to do something with IOs here... */ + return res->start; +#endif +} + +/* Obsolete functions. Should be removed once the symbios driver + * is fixed + */ +unsigned long +pci_phys_to_bus(unsigned long pa, int busnr) +{ +#ifdef CONFIG_POWER4 + return pa - pci_address_offset(busnr, IORESOURCE_MEM); +#else /* CONFIG_POWER4 */ + struct pci_controller* hose = pci_bus_to_hose(busnr); + if (!hose) + return pa; + return pa - hose->pci_mem_offset; +#endif +} + +unsigned long +pci_bus_to_phys(unsigned int ba, int busnr) +{ +#ifdef CONFIG_POWER4 + return ba + pci_address_offset(dev->bus->number, IORESOURCE_MEM); +#else /* CONFIG_POWER4 */ + struct pci_controller* hose = pci_bus_to_hose(busnr); + if (!hose) + return ba; + return ba + hose->pci_mem_offset; +#endif } /* Provide information on locations of various I/O regions in physical @@ -430,23 +805,93 @@ * Note that the returned IO or memory base is a physical address */ -asmlinkage long +long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) { + struct pci_controller* hose = pci_bus_to_hose(bus); long result = -EOPNOTSUPP; + + if (!hose) + return -ENODEV; switch (which) { case IOBASE_BRIDGE_NUMBER: - return (long)pci_dev_root_bridge(bus, devfn); + return (long)hose->first_busno; case IOBASE_MEMORY: - return (long)pci_dev_mem_base(bus, devfn); + return (long)hose->pci_mem_offset; case IOBASE_IO: - result = (long)pci_dev_io_base(bus, devfn, 1); - if (result == 0) - result = -EOPNOTSUPP; - break; + return (long)hose->io_base_phys; + case IOBASE_ISA_IO: + return (long)isa_io_base; + case IOBASE_ISA_MEM: + return (long)isa_mem_base; } return result; } +/* + * Null PCI config access functions, for the case when we can't + * find a hose. + */ +#define NULL_PCI_OP(rw, size, type) \ +static int \ +null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + return PCIBIOS_DEVICE_NOT_FOUND; \ +} + +NULL_PCI_OP(read, byte, u8 *) +NULL_PCI_OP(read, word, u16 *) +NULL_PCI_OP(read, dword, u32 *) +NULL_PCI_OP(write, byte, u8) +NULL_PCI_OP(write, word, u16) +NULL_PCI_OP(write, dword, u32) + +static struct pci_ops null_pci_ops = +{ + null_read_config_byte, + null_read_config_word, + null_read_config_dword, + null_write_config_byte, + null_write_config_word, + null_write_config_dword +}; + +/* + * These functions are used early on before PCI scanning is done + * and all of the pci_dev and pci_bus structures have been created. + */ +static struct pci_dev * +fake_pci_dev(struct pci_controller *hose, int busnr, int devfn) +{ + static struct pci_dev dev; + static struct pci_bus bus; + + if (hose == 0) { + hose = pci_bus_to_hose(busnr); + if (hose == 0) + printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr); + } + dev.bus = &bus; + dev.sysdata = hose; + dev.devfn = devfn; + bus.number = busnr; + bus.ops = hose? hose->ops: &null_pci_ops; + return &dev; +} + +#define EARLY_PCI_OP(rw, size, type) \ +int early_##rw##_config_##size(struct pci_controller *hose, int bus, \ + int devfn, int offset, type value) \ +{ \ + return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \ + offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) +EARLY_PCI_OP(read, word, u16 *) +EARLY_PCI_OP(read, dword, u32 *) +EARLY_PCI_OP(write, byte, u8) +EARLY_PCI_OP(write, word, u16) +EARLY_PCI_OP(write, dword, u32) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/pci.h linux.ac/arch/ppc/kernel/pci.h --- linux-2.4.0/arch/ppc/kernel/pci.h Tue Aug 31 19:36:43 1999 +++ linux.ac/arch/ppc/kernel/pci.h Mon Dec 18 20:45:15 2000 @@ -2,47 +2,23 @@ #ifndef __PPC_KERNEL_PCI_H__ #define __PPC_KERNEL_PCI_H__ +/* Configure those in your xxx_init() or xxx_setup_arch() function */ extern unsigned long isa_io_base; extern unsigned long isa_mem_base; extern unsigned long pci_dram_offset; -extern unsigned int *pci_config_address; -extern unsigned char *pci_config_data; +/* Set this to 1 if you want the kernel to re-assign all PCI + * bus numbers + */ +extern int pci_assign_all_busses; -void fix_intr(struct device_node *node, struct pci_dev *dev); -#if 0 -#define decl_config_access_method(name) \ -struct pci_ops name##_pci_ops = { \ - name##_pcibios_read_config_byte, \ - name##_pcibios_read_config_word, \ - name##_pcibios_read_config_dword, \ - name##_pcibios_write_config_byte, \ - name##_pcibios_write_config_word, \ - name##_pcibios_write_config_dword \ -} -#endif +extern struct pci_controller* pcibios_alloc_controller(void); +extern struct pci_controller* pci_find_hose_for_OF_device( + struct device_node* node); -#define decl_config_access_method(name) \ -extern int name##_pcibios_read_config_byte(unsigned char bus, \ - unsigned char dev_fn, unsigned char offset, unsigned char *val); \ -extern int name##_pcibios_read_config_word(unsigned char bus, \ - unsigned char dev_fn, unsigned char offset, unsigned short *val); \ -extern int name##_pcibios_read_config_dword(unsigned char bus, \ - unsigned char dev_fn, unsigned char offset, unsigned int *val); \ -extern int name##_pcibios_write_config_byte(unsigned char bus, \ - unsigned char dev_fn, unsigned char offset, unsigned char val); \ -extern int name##_pcibios_write_config_word(unsigned char bus, \ - unsigned char dev_fn, unsigned char offset, unsigned short val); \ -extern int name##_pcibios_write_config_dword(unsigned char bus, \ - unsigned char dev_fn, unsigned char offset, unsigned int val) - -#define set_config_access_method(name) \ - ppc_md.pcibios_read_config_byte = name##_pcibios_read_config_byte; \ - ppc_md.pcibios_read_config_word = name##_pcibios_read_config_word; \ - ppc_md.pcibios_read_config_dword = name##_pcibios_read_config_dword; \ - ppc_md.pcibios_write_config_byte = name##_pcibios_write_config_byte; \ - ppc_md.pcibios_write_config_word = name##_pcibios_write_config_word; \ - ppc_md.pcibios_write_config_dword = name##_pcibios_write_config_dword +extern void setup_indirect_pci(struct pci_controller* hose, + u32 cfg_addr, u32 cfg_data); +extern void setup_grackle(struct pci_controller *hose, unsigned io_space_size); #endif /* __PPC_KERNEL_PCI_H__ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/pmac_pci.c linux.ac/arch/ppc/kernel/pmac_pci.c --- linux-2.4.0/arch/ppc/kernel/pmac_pci.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/pmac_pci.c Mon Dec 18 20:45:24 2000 @@ -27,23 +27,14 @@ #include "pci.h" -struct bridge_data **bridges, *bridge_list; -static int max_bus; - -struct uninorth_data { - struct device_node* node; - volatile unsigned int* cfg_addr; - volatile unsigned int* cfg_data; - void* iobase; - unsigned long iobase_phys; -}; - -static struct uninorth_data uninorth_bridges[3]; -static int uninorth_count; -static int uninorth_default = -1; +#undef DEBUG static void add_bridges(struct device_node *dev); +/* XXX Could be per-controller, but I don't think we risk anything by + * assuming we won't have both UniNorth and Bandit */ +static int has_uninorth; + /* * Magic constants for enabling cache coherency in the bandit/PSX bridge. */ @@ -56,477 +47,201 @@ #define BANDIT_MAGIC 0x50 #define BANDIT_COHERENT 0x40 -/* Obsolete, should be replaced by pmac_pci_dev_io_base() (below) */ -__pmac -void *pci_io_base(unsigned int bus) +static int __init +fixup_one_level_bus_range(struct device_node *node, int higher) { - struct bridge_data *bp; - - if (bus > max_bus || (bp = bridges[bus]) == 0) - return 0; - return bp->io_base; -} - -__pmac -int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, - unsigned char *devfn_ptr) -{ - unsigned int *reg; - int len; + for (; node != 0;node = node->sibling) { + int * bus_range; + unsigned int *class_code; + 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; + /* For PCI<->PCI bridges or CardBus bridges, we go down */ + class_code = (unsigned int *) get_property(node, "class-code", 0); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + bus_range = (int *) get_property(node, "bus-range", &len); + if (bus_range != NULL && len > 2 * sizeof(int)) { + if (bus_range[1] > higher) + higher = bus_range[1]; + } + higher = fixup_one_level_bus_range(node->child, higher); } - *bus_ptr = reg[0] >> 16; - *devfn_ptr = reg[0] >> 8; - return 0; + return higher; } -/* This routines figures out on which root bridge a given PCI device - * is attached. +/* This routine fixes the "bus-range" property of all bridges in the + * system since they tend to have their "last" member wrong on macs + * + * Note that the bus numbers manipulated here are OF bus numbers, they + * are not Linux bus numbers. */ -__pmac -int -pmac_pci_dev_root_bridge(unsigned char bus, unsigned char dev_fn) +static void __init +fixup_bus_range(struct device_node *bridge) { - struct device_node *node, *bridge_node; - int bridge = uninorth_default; - - if (uninorth_count == 0) - return 0; - if (bus == 0 && PCI_SLOT(dev_fn) < 11) - return 0; + int * bus_range; + int len; - /* We look for the OF device corresponding to this bus/devfn pair. If we - * don't find it, we default to the external PCI */ - bridge_node = NULL; - node = find_pci_device_OFnode(bus, dev_fn & 0xf8); - if (node) { - /* note: we don't stop on the first occurence since we need to go - * up to the root bridge */ - do { - if (node->type && !strcmp(node->type, "pci") - && device_is_compatible(node, "uni-north")) - bridge_node = node; - node=node->parent; - } while (node); - } - if (bridge_node) { - int i; - for (i=0;i max_bus || (bp = bridges[bus]) == 0) - return 0; - return physical ? (void *) bp->io_base_phys : bp->io_base; + /* Lookup the "bus-range" property for the hose */ + bus_range = (int *) get_property(bridge, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + bridge->full_name); + return; } - return physical ? (void *) uninorth_bridges[bridge].iobase_phys - : uninorth_bridges[bridge].iobase; + bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } -__pmac -void * -pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn) -{ - return 0; -} - -/* This function only works for bus 0, uni-N uses a different mecanism for - * other busses (see below) +/* + * Apple MacRISC (UniNorth, Bandit) PCI controllers. + * + * The "Bandit" version is present in all early PCI PowerMacs, + * and up to the first ones using Grackle. Some machines may + * have 2 bandit controllers (2 PCI busses). + * + * The "UniNorth" version is present in all Core99 machines + * (iBook, G4, new IMacs, and all the recent Apple machines). + * It contains 3 controllers in one ASIC. */ -#define UNI_N_CFA0(devfn, off) \ + +#define MACRISC_CFA0(devfn, off) \ ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ | (((unsigned long)(off)) & 0xFCUL)) -/* This one is for type 1 config accesses */ -#define UNI_N_CFA1(bus, devfn, off) \ +#define MACRISC_CFA1(bus, devfn, off) \ ((((unsigned long)(bus)) << 16) \ |(((unsigned long)(devfn)) << 8) \ |(((unsigned long)(off)) & 0xFCUL) \ |1UL) -__pmac static -unsigned int -uni_north_access_data(unsigned char bus, unsigned char dev_fn, - unsigned char offset) +static unsigned int __pmac +macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) { - int bridge; unsigned int caddr; - - bridge = pmac_pci_dev_root_bridge(bus, dev_fn); - if (bus == 0) - caddr = UNI_N_CFA0(dev_fn, offset); - else - caddr = UNI_N_CFA1(bus, dev_fn, offset); - - if (bridge == -1) { - printk(KERN_WARNING "pmac_pci: no default bridge !\n"); - return 0; - } - - /* Uninorth will return garbage if we don't read back the value ! */ - out_le32(uninorth_bridges[bridge].cfg_addr, caddr); - (void)in_le32(uninorth_bridges[bridge].cfg_addr); - /* Yes, offset is & 7, not & 3 ! */ - return (unsigned int)(uninorth_bridges[bridge].cfg_data) + (offset & 0x07); -} - -__pmac -int uni_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - unsigned int addr; - - *val = 0xff; - addr = uni_north_access_data(bus, dev_fn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - *val = in_8((volatile unsigned char*)addr); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -int uni_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - unsigned int addr; - - *val = 0xffff; - addr = uni_north_access_data(bus, dev_fn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - *val = in_le16((volatile unsigned short*)addr); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -int uni_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - unsigned int addr; - - *val = 0xffff; - addr = uni_north_access_data(bus, dev_fn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - *val = in_le32((volatile unsigned int*)addr); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -int uni_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - unsigned int addr; - - addr = uni_north_access_data(bus, dev_fn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - out_8((volatile unsigned char *)addr, val); - (void)in_8((volatile unsigned char *)addr); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -int uni_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - unsigned int addr; - - addr = uni_north_access_data(bus, dev_fn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - out_le16((volatile unsigned short *)addr, val); - (void)in_le16((volatile unsigned short *)addr); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -int uni_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - unsigned int addr; - addr = uni_north_access_data(bus, dev_fn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - out_le32((volatile unsigned int *)addr, val); - (void)in_le32((volatile unsigned int *)addr); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -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 { - /* Bus number once again taken into consideration. - * Change applied from 2.1.24. This makes devices located - * behind PCI-PCI bridges visible. - * -Ranjit Deshpande, 01/20/99 - */ - out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1); - } - udelay(2); - *val = in_8(bp->cfg_data + (offset & 3)); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -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) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 1) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - 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 { - /* See pci_read_config_byte */ - out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1); - } - udelay(2); - *val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3))); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -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) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 3) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - 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 { - /* See pci_read_config_byte */ - out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + offset + 1); - } - udelay(2); - *val = in_le32((volatile unsigned int *)bp->cfg_data); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -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) { +#ifdef DEBUG +// printk("macrisc_config_access(hose: 0x%08lx, bus: 0x%x, devfb: 0x%x, offset: 0x%x)\n", +// hose, bus, dev_fn, offset); +#endif + if (bus == hose->first_busno) { 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 { - /* See pci_read_config_byte */ - out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1); - } - udelay(2); - out_8(bp->cfg_data + (offset & 3), val); - return PCIBIOS_SUCCESSFUL; -} + return 0; + caddr = MACRISC_CFA0(dev_fn, offset); + } else + caddr = MACRISC_CFA1(bus, dev_fn, offset); + + /* Uninorth will return garbage if we don't read back the value ! */ + do { + out_le32(hose->cfg_addr, caddr); + } while(in_le32(hose->cfg_addr) != caddr); + + offset &= has_uninorth ? 0x07 : 0x03; + return (unsigned int)(hose->cfg_data) + (unsigned int)offset; +} + +#define cfg_read(val, addr, type, op, op2) \ + *val = op((type)(addr)) +#define cfg_write(val, addr, type, op, op2) \ + op((type *)(addr), (val)); (void) op2((type *)(addr)) + +#define cfg_read_bad(val, size) *val = bad_##size; +#define cfg_write_bad(val, size) + +#define bad_byte 0xff +#define bad_word 0xffff +#define bad_dword 0xffffffffU + +#define MACRISC_PCI_OP(rw, size, type, op, op2) \ +static int __pmac \ +macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val) \ +{ \ + struct pci_controller *hose = dev->sysdata; \ + unsigned int addr; \ + \ + addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \ + if (!addr) { \ + cfg_##rw##_bad(val, size) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ + } \ + cfg_##rw(val, addr, type, op, op2); \ + return PCIBIOS_SUCCESSFUL; \ +} + +MACRISC_PCI_OP(read, byte, u8 *, in_8, x) +MACRISC_PCI_OP(read, word, u16 *, in_le16, x) +MACRISC_PCI_OP(read, dword, u32 *, in_le32, x) +MACRISC_PCI_OP(write, byte, u8, out_8, in_8) +MACRISC_PCI_OP(write, word, u16, out_le16, in_le16) +MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32) + +static struct pci_ops macrisc_pci_ops = +{ + macrisc_read_config_byte, + macrisc_read_config_word, + macrisc_read_config_dword, + macrisc_write_config_byte, + macrisc_write_config_word, + macrisc_write_config_dword +}; -__pmac -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) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 1) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - 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 { - /* See pci_read_config_byte */ - out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1); - } - udelay(2); - out_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)), val); - return PCIBIOS_SUCCESSFUL; -} - -__pmac -int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) +/* + * Apple "Chaos" PCI controller. + * + * This controller is present on some first generation "PowerSurge" + * machines (8500, 8600, ...). It's a very weird beast and will die + * in flames if we try to probe the config space. + * The long-term solution is to provide a config space "emulation" + * based on what we find in OF device tree + */ + +static int chaos_config_read_byte(struct pci_dev *dev, int offset, u8 *val) { - struct bridge_data *bp; - - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 3) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - 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 { - /* See pci_read_config_byte */ - out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1); - } - udelay(2); - out_le32((volatile unsigned int *)bp->cfg_data, val); - return PCIBIOS_SUCCESSFUL; + return PCIBIOS_DEVICE_NOT_FOUND; } -#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ - | (((o) & ~3) << 24)) - -int grackle_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) +static int chaos_config_read_word(struct pci_dev *dev, int offset, u16 *val) { - struct bridge_data *bp; - - *val = 0xff; - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset)); - *val = in_8(bp->cfg_data + (offset & 3)); - return PCIBIOS_SUCCESSFUL; + return PCIBIOS_DEVICE_NOT_FOUND; } -int grackle_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) +static int chaos_config_read_dword(struct pci_dev *dev, int offset, u32 *val) { - struct bridge_data *bp; - - *val = 0xffff; - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 1) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset)); - *val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset&3))); - return PCIBIOS_SUCCESSFUL; + return PCIBIOS_DEVICE_NOT_FOUND; } -int grackle_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) +static int chaos_config_write_byte(struct pci_dev *dev, int offset, u8 val) { - struct bridge_data *bp; - - *val = 0xffffffff; - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 3) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset)); - *val = in_le32((volatile unsigned int *)bp->cfg_data); - return PCIBIOS_SUCCESSFUL; + return PCIBIOS_DEVICE_NOT_FOUND; } -int grackle_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) +static int chaos_config_write_word(struct pci_dev *dev, int offset, u16 val) { - struct bridge_data *bp; - - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset)); - out_8(bp->cfg_data + (offset & 3), val); - return PCIBIOS_SUCCESSFUL; + return PCIBIOS_DEVICE_NOT_FOUND; } -int grackle_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) +static int chaos_config_write_dword(struct pci_dev *dev, int offset, u32 val) { - struct bridge_data *bp; - - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 1) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset)); - out_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)), val); - return PCIBIOS_SUCCESSFUL; + return PCIBIOS_DEVICE_NOT_FOUND; } -int grackle_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) +static struct pci_ops chaos_pci_ops = { - struct bridge_data *bp; + chaos_config_read_byte, + chaos_config_read_word, + chaos_config_read_dword, + chaos_config_write_byte, + chaos_config_write_word, + chaos_config_write_dword +}; - if (bus > max_bus || (bp = bridges[bus]) == 0) - return PCIBIOS_DEVICE_NOT_FOUND; - if ((offset & 1) != 0) - return PCIBIOS_BAD_REGISTER_NUMBER; - out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset)); - out_le32((volatile unsigned int *)bp->cfg_data, val); - return PCIBIOS_SUCCESSFUL; -} /* * 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. + * N.B. we could clean this up using the hose ops directly. */ -static void __init init_bandit(struct bridge_data *bp) +static void __init init_bandit(struct pci_controller *bp) { unsigned int vendev, magic; int rev; @@ -543,8 +258,8 @@ 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); + "Unknown revision %d for bandit at %08lx\n", + rev, bp->io_base_phys); } else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) { printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); return; @@ -555,8 +270,8 @@ 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); + printk(KERN_WARNING "Unknown revision %d for bandit at %08lx\n", + rev, bp->io_base_phys); /* read the word at offset 0x50 */ out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); @@ -567,16 +282,71 @@ 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); + printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %08lx\n", + bp->io_base_phys); +} + + +/* + * Tweak the PCI-PCI bridge chip on the blue & white G3s. + */ +static void __init +init_p2pbridge(void) +{ + struct device_node *p2pbridge; + struct pci_controller* hose; + u8 bus, devfn; + u16 val; + + /* XXX it would be better here to identify the specific + PCI-PCI bridge chip we have. */ + if ((p2pbridge = find_devices("pci-bridge")) == 0 + || p2pbridge->parent == NULL + || strcmp(p2pbridge->parent->name, "pci") != 0) + return; + if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { +#ifdef DEBUG + printk("Can't find PCI infos for PCI<->PCI bridge\n"); +#endif + return; + } + /* Warning: At this point, we have not yet renumbered all busses. + * So we must use OF walking to find out hose + */ + hose = pci_find_hose_for_OF_device(p2pbridge); + if (!hose) { +#ifdef DEBUG + printk("Can't find hose for PCI<->PCI bridge\n"); +#endif + return; + } + if (early_read_config_word(hose, bus, devfn, + PCI_BRIDGE_CONTROL, &val) < 0) { + printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); + return; + } + val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; + early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); } +void __init +pmac_find_bridges(void) +{ + add_bridges(find_devices("bandit")); + add_bridges(find_devices("chaos")); + add_bridges(find_devices("pci")); + init_p2pbridge(); +} + +#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ + | (((o) & ~3) << 24)) + #define GRACKLE_PICR1_STG 0x00000040 #define GRACKLE_PICR1_LOOPSNOOP 0x00000010 /* N.B. this is called before bridges is initialized, so we can't use grackle_pcibios_{read,write}_config_dword. */ -static inline void grackle_set_stg(struct bridge_data *bp, int enable) +static inline void grackle_set_stg(struct pci_controller* bp, int enable) { unsigned int val; @@ -586,9 +356,10 @@ (val & ~GRACKLE_PICR1_STG); out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); out_le32((volatile unsigned int *)bp->cfg_data, val); + (void)in_le32((volatile unsigned int *)bp->cfg_data); } -static inline void grackle_set_loop_snoop(struct bridge_data *bp, int enable) +static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable) { unsigned int val; @@ -598,25 +369,68 @@ (val & ~GRACKLE_PICR1_LOOPSNOOP); out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); out_le32((volatile unsigned int *)bp->cfg_data, val); + (void)in_le32((volatile unsigned int *)bp->cfg_data); } +static void __init +setup_uninorth(struct pci_controller* hose, struct reg_property* addr) +{ + pci_assign_all_busses = 1; + has_uninorth = 1; + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); + hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); + hose->io_base_phys = addr->address; + /* is 0x10000 enough for io space ? */ + hose->io_base_virt = (void *)ioremap(addr->address, 0x10000); + + /* XXX This is the bridge with the PCI expansion bus. We route + * legacy IOs to it. + */ + if (addr->address == 0xf2000000) + isa_io_base = (unsigned long)hose->io_base_virt; +} -void __init pmac_find_bridges(void) +static void __init +setup_bandit(struct pci_controller* hose, struct reg_property* addr) { - int bus; - struct bridge_data *bridge; + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = (volatile unsigned int *) + ioremap(addr->address + 0x800000, 0x1000); + hose->cfg_data = (volatile unsigned char *) + ioremap(addr->address + 0xc00000, 0x1000); + hose->io_base_phys = addr->address; + hose->io_base_virt = (void *) ioremap(addr->address, 0x10000); + init_bandit(hose); +} + +static void __init +setup_chaos(struct pci_controller* hose, struct reg_property* addr) +{ + /* assume a `chaos' bridge */ + hose->ops = &chaos_pci_ops; + hose->cfg_addr = (volatile unsigned int *) + ioremap(addr->address + 0x800000, 0x1000); + hose->cfg_data = (volatile unsigned char *) + ioremap(addr->address + 0xc00000, 0x1000); + hose->io_base_phys = addr->address; + hose->io_base_virt = (void *) ioremap(addr->address, 0x10000); +} - bridge_list = 0; - max_bus = 0; - add_bridges(find_devices("bandit")); - add_bridges(find_devices("chaos")); - add_bridges(find_devices("pci")); - bridges = (struct bridge_data **) - alloc_bootmem((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; +void __init +setup_grackle(struct pci_controller *hose, unsigned io_space_size) +{ + setup_indirect_pci(hose, 0xfec00000, 0xfee00000); + hose->io_base_phys = 0xfe000000; + hose->io_base_virt = (void *) ioremap(0xfe000000, io_space_size); + pci_dram_offset = 0; + isa_mem_base = 0xfd000000; + isa_io_base = (unsigned long) hose->io_base_virt; + if (machine_is_compatible("AAPL,PowerBook1998")) + grackle_set_loop_snoop(hose, 1); +#if 0 /* Disabled for now, HW problems ??? */ + grackle_set_stg(hose, 1); +#endif } /* @@ -626,11 +440,12 @@ */ static void __init add_bridges(struct device_node *dev) { - int *bus_range; int len; - struct bridge_data *bp; + struct pci_controller *hose; struct reg_property *addr; - + char* disp_name; + int *bus_range; + for (; dev != NULL; dev = dev->next) { addr = (struct reg_property *) get_property(dev, "reg", &len); if (addr == NULL || len < sizeof(*addr)) { @@ -640,108 +455,52 @@ } 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, addr->address); - if (device_is_compatible(dev, "uni-north")) { - int i = uninorth_count++; - uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000); - uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000); - uninorth_bridges[i].node = dev; - uninorth_bridges[i].iobase_phys = addr->address; - /* is 0x10000 enough for io space ? */ - uninorth_bridges[i].iobase = (void *)ioremap(addr->address, 0x10000); - /* XXX This is the bridge with the PCI expansion bus. This is also the - * address of the bus that will receive type 1 config accesses and io - * accesses. Appears to be correct for iMac DV and G4 Sawtooth too. - * That means that we cannot do io cycles on the AGP bus nor the internal - * ethernet/fw bus. Fortunately, they appear not to be needed on iMac DV - * and G4 neither. - */ - if (addr->address == 0xf2000000) - uninorth_default = i; - else - continue; + printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", + dev->full_name); } - bp = (struct bridge_data *) alloc_bootmem(sizeof(*bp)); + hose = pcibios_alloc_controller(); + if (!hose) + continue; + hose->arch_data = dev; + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + disp_name = NULL; if (device_is_compatible(dev, "uni-north")) { - bp->cfg_addr = 0; - bp->cfg_data = 0; - bp->io_base = uninorth_bridges[uninorth_count-1].iobase; - bp->io_base_phys = uninorth_bridges[uninorth_count-1].iobase_phys; + setup_uninorth(hose, addr); + disp_name = "UniNorth"; } else if (strcmp(dev->name, "pci") == 0) { /* XXX assume this is a mpc106 (grackle) */ - bp->cfg_addr = (volatile unsigned int *) - ioremap(0xfec00000, 0x1000); - bp->cfg_data = (volatile unsigned char *) - ioremap(0xfee00000, 0x1000); - bp->io_base_phys = 0xfe000000; - bp->io_base = (void *) ioremap(0xfe000000, 0x20000); - if (machine_is_compatible("AAPL,PowerBook1998")) - grackle_set_loop_snoop(bp, 1); -#if 0 /* Disabled for now, HW problems ??? */ - grackle_set_stg(bp, 1); -#endif - } else { - /* a `bandit' or `chaos' bridge */ - bp->cfg_addr = (volatile unsigned int *) - ioremap(addr->address + 0x800000, 0x1000); - bp->cfg_data = (volatile unsigned char *) - ioremap(addr->address + 0xc00000, 0x1000); - bp->io_base_phys = addr->address; - bp->io_base = (void *) ioremap(addr->address, 0x10000); + setup_grackle(hose, 0x20000); + disp_name = "Grackle (MPC106)"; + } else if (strcmp(dev->name, "bandit") == 0) { + setup_bandit(hose, addr); + disp_name = "Bandit"; + } else if (strcmp(dev->name, "chaos") == 0) { + setup_chaos(hose, addr); + disp_name = "Chaos"; } + printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n", + disp_name, addr->address, hose->first_busno, hose->last_busno); +#ifdef DEBUG + printk(" ->Hose at 0x%08lx, cfg_addr=0x%08lx,cfg_data=0x%08lx\n", + hose, hose->cfg_addr, hose->cfg_data); +#endif + + /* Setup a default isa_io_base */ if (isa_io_base == 0) - isa_io_base = (unsigned long) bp->io_base; - 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; + isa_io_base = (unsigned long)hose->io_base_virt; - if (strcmp(dev->name, "bandit") == 0) - init_bandit(bp); + /* Fixup "bus-range" OF property */ + fixup_bus_range(dev); } } -/* Recursively searches any node that is of type PCI-PCI bridge. Without - * this, the old code would miss children of P2P bridges and hence not - * fix IRQ's for cards located behind P2P bridges. - * - Ranjit Deshpande, 01/20/99 - */ -void __init -fix_intr(struct device_node *node, struct pci_dev *dev) -{ - unsigned int *reg, *class_code; - - for (; node != 0;node = node->sibling) { - class_code = (unsigned int *) get_property(node, "class-code", 0); - if(class_code && (*class_code >> 8) == PCI_CLASS_BRIDGE_PCI) - fix_intr(node->child, dev); - reg = (unsigned int *) get_property(node, "reg", 0); - if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn) - continue; - /* this is the node, see if it has interrupts */ - if (node->n_intrs > 0) - dev->irq = node->intrs[0].line; - break; - } -} - -void __init -pmac_pcibios_fixup(void) -{ - struct pci_dev *dev; +static void +pcibios_fixup_OF_interrupts(void) +{ + struct pci_dev* dev; /* * FIXME: This is broken: We should not assign IRQ's to IRQless @@ -757,44 +516,43 @@ * should find the device node and se if it has an * AAPL,interrupts property. */ - struct bridge_data *bp = bridges[dev->bus->number]; unsigned char pin; + struct device_node* node; - if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) || - !pin) + if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) || !pin) continue; /* No interrupt generated -> no fixup */ - /* We iterate all instances of uninorth for now */ - if (uninorth_count && dev->bus->number == 0) { - int i; - for (i=0;ichild, dev); - } else - fix_intr(bp->node->child, dev); + node = pci_device_to_OF_node(dev); + if (!node) { + printk("No OF node for device %x:%x\n", dev->bus->number, dev->devfn >> 3); + continue; + } + /* this is the node, see if it has interrupts */ + if (node->n_intrs > 0) + dev->irq = node->intrs[0].line; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } } void __init -pmac_setup_pci_ptrs(void) +pmac_pcibios_fixup(void) { - struct device_node* np; + /* Fixup interrupts according to OF tree */ + pcibios_fixup_OF_interrupts(); +} - np = find_devices("pci"); - if (np != 0) - { - if (device_is_compatible(np, "uni-north")) - { - /* looks like an Core99 powermac */ - set_config_access_method(uni); - } else - { - /* looks like a G3 powermac */ - set_config_access_method(grackle); - } - } else - { - set_config_access_method(pmac); +/* We don't want to enable USB controllers absent from the OF tree + * (iBook second controller) + */ +int +pmac_pci_enable_device_hook(struct pci_dev *dev) +{ + if (dev->vendor == PCI_VENDOR_ID_APPLE + && dev->device == PCI_DEVICE_ID_APPLE_KL_USB) { + struct device_node* node; + node = pci_device_to_OF_node(dev); + if (!node) + return -EINVAL; } - - ppc_md.pcibios_fixup = pmac_pcibios_fixup; + return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/pmac_pic.c linux.ac/arch/ppc/kernel/pmac_pic.c --- linux-2.4.0/arch/ppc/kernel/pmac_pic.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/pmac_pic.c Mon Dec 18 20:45:24 2000 @@ -4,14 +4,15 @@ #include #include #include -#include #include #include #include #include #include + #include "pmac_pic.h" +#include "open_pic.h" /* pmac */struct pmac_irq_hw { unsigned int flag; @@ -30,16 +31,14 @@ static int max_irqs; static int max_real_irqs; -static int has_openpic = 0; +static int pmac_has_openpic; + +spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED; + #define GATWICK_IRQ_POOL_SIZE 10 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; -extern int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val); -extern int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val); - /* * Mark an irq as "lost". This is only used on the pmac * since it can lose interrupts (see pmac_set_irq_mask). @@ -51,48 +50,11 @@ atomic_inc(&ppc_n_lost_interrupts); } -static void pmac_openpic_mask_irq(unsigned int irq_nr) -{ - openpic_disable_irq(irq_nr); -} - -static void pmac_openpic_unmask_irq(unsigned int irq_nr) -{ - openpic_enable_irq(irq_nr); -} - -static void pmac_openpic_ack_irq(unsigned int irq_nr) -{ - if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) - openpic_eoi(smp_processor_id()); - openpic_disable_irq(irq_nr); -} - -static void pmac_openpic_end_irq(unsigned int irq_nr) -{ - if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0) - openpic_eoi(smp_processor_id()); - openpic_enable_irq(irq_nr); -} - -struct hw_interrupt_type pmac_open_pic = { - " OpenPIC ", - NULL, - NULL, - pmac_openpic_unmask_irq, - pmac_openpic_mask_irq, - /* Theorically, the mask&ack should be NULL for OpenPIC. However, doing - * so shows tons of bogus interrupts coming in. - */ - pmac_openpic_ack_irq, - pmac_openpic_end_irq, - NULL -}; - static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr) { unsigned long bit = 1UL << (irq_nr & 0x1f); int i = irq_nr >> 5; + unsigned long flags; if ((unsigned)irq_nr >= max_irqs) return; @@ -100,6 +62,7 @@ clear_bit(irq_nr, ppc_cached_irq_mask); if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) atomic_dec(&ppc_n_lost_interrupts); + spin_lock_irqsave(&pmac_pic_lock, flags); out_le32(&pmac_irq_hw[i]->ack, bit); out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); out_le32(&pmac_irq_hw[i]->ack, bit); @@ -108,16 +71,19 @@ interrupts */ mb(); } while(in_le32(&pmac_irq_hw[i]->flag) & bit); + spin_unlock_irqrestore(&pmac_pic_lock, flags); } static void __pmac pmac_set_irq_mask(unsigned int irq_nr) { unsigned long bit = 1UL << (irq_nr & 0x1f); int i = irq_nr >> 5; + unsigned long flags; if ((unsigned)irq_nr >= max_irqs) return; + spin_lock_irqsave(&pmac_pic_lock, flags); /* enable unmasked interrupts */ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); @@ -137,6 +103,7 @@ && (ld_le32(&pmac_irq_hw[i]->level) & bit) && !(ld_le32(&pmac_irq_hw[i]->flag) & bit)) __set_lost((ulong)irq_nr); + spin_unlock_irqrestore(&pmac_pic_lock, flags); } static void __pmac pmac_mask_irq(unsigned int irq_nr) @@ -152,6 +119,15 @@ pmac_set_irq_mask(irq_nr); } +static void __pmac pmac_end_irq(unsigned int irq_nr) +{ + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + set_bit(irq_nr, ppc_cached_irq_mask); + pmac_set_irq_mask(irq_nr); + } +} + + struct hw_interrupt_type pmac_pic = { " PMAC-PIC ", NULL, @@ -159,7 +135,7 @@ pmac_unmask_irq, pmac_mask_irq, pmac_mask_and_ack_irq, - pmac_unmask_irq, + pmac_end_irq, NULL }; @@ -170,7 +146,7 @@ pmac_unmask_irq, pmac_mask_irq, pmac_mask_and_ack_irq, - pmac_unmask_irq, + pmac_end_irq, NULL }; @@ -204,35 +180,22 @@ unsigned long bits = 0; #ifdef CONFIG_SMP - void pmac_smp_message_recv(struct pt_regs *); + void psurge_smp_message_recv(struct pt_regs *); - /* IPI's are a hack on the powersurge -- Cort */ - if ( smp_processor_id() != 0 ) - { - pmac_smp_message_recv(regs); + /* IPI's are a hack on the powersurge -- Cort */ + if ( smp_processor_id() != 0 ) { + psurge_smp_message_recv(regs); return -2; /* ignore, already handled */ } #endif /* CONFIG_SMP */ - - if (has_openpic) { - irq = openpic_irq(smp_processor_id()); - if (irq == OPENPIC_VEC_SPURIOUS) - /* We get those when doing polled ADB requests, - * using -2 is a temp hack to disable the printk - */ - irq = -2; /*-1; */ - } - else - { - for (irq = max_real_irqs; (irq -= 32) >= 0; ) { - int i = irq >> 5; - bits = ld_le32(&pmac_irq_hw[i]->flag) - | ppc_lost_interrupts[i]; - if (bits == 0) - continue; - irq += __ilog2(bits); - break; - } + for (irq = max_real_irqs; (irq -= 32) >= 0; ) { + int i = irq >> 5; + bits = ld_le32(&pmac_irq_hw[i]->flag) + | ppc_lost_interrupts[i]; + if (bits == 0) + continue; + irq += __ilog2(bits); + break; } return irq; @@ -336,11 +299,16 @@ addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); max_irqs = 64; - if (pci_device_loc(irqctrler, &bus, &devfn) == 0) { - pmac_pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - cmd &= ~PCI_COMMAND_IO; - pmac_pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) { + struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler); + if (!hose) + printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); + else { + early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + cmd &= ~PCI_COMMAND_IO; + early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); + } } second_irq = irqctrler->intrs[0].line; @@ -378,20 +346,26 @@ printk("PowerMac using OpenPIC irq controller\n"); if (irqctrler->n_addrs > 0) { + int nmi_irq = -1; + unsigned char senses[NR_IRQS]; #ifdef CONFIG_XMON struct device_node* pswitch; -#endif /* CONFIG_XMON */ - OpenPIC = (volatile struct OpenPIC *) - ioremap(irqctrler->addrs[0].address, - irqctrler->addrs[0].size); - for ( i = 0 ; i < NR_IRQS ; i++ ) - irq_desc[i].handler = &pmac_open_pic; - openpic_init(1); - has_openpic = 1; -#ifdef CONFIG_XMON + pswitch = find_devices("programmer-switch"); if (pswitch && pswitch->n_intrs) - request_irq(pswitch->intrs[0].line, xmon_irq, 0, + nmi_irq = pswitch->intrs[0].line; +#endif /* CONFIG_XMON */ + prom_get_irq_senses(senses, 0, NR_IRQS); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = NR_IRQS; + ppc_md.get_irq = openpic_get_irq; + OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, + irqctrler->addrs[0].size); + openpic_init(1, 0, 0, nmi_irq); + pmac_has_openpic = 1; +#ifdef CONFIG_XMON + if (nmi_irq >= 0) + request_irq(nmi_irq, xmon_irq, 0, "NMI - XMON", 0); #endif /* CONFIG_XMON */ return; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/pmac_setup.c linux.ac/arch/ppc/kernel/pmac_setup.c --- linux-2.4.0/arch/ppc/kernel/pmac_setup.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/pmac_setup.c Fri Dec 22 16:36:26 2000 @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -73,7 +74,8 @@ extern int pmac_set_rtc_time(unsigned long nowtime); extern void pmac_read_rtc_time(void); extern void pmac_calibrate_decr(void); -extern void pmac_setup_pci_ptrs(void); +extern void pmac_pcibios_fixup(void); +extern void pmac_find_bridges(void); extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int mackbd_getkeycode(unsigned int scancode); @@ -99,9 +101,7 @@ extern int keyboard_sends_linux_keycodes; extern void pmac_nvram_update(void); -extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical); -extern void *pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn); -extern int pmac_pci_dev_root_bridge(unsigned char bus, unsigned char devfn); +extern int pmac_pci_enable_device_hook(struct pci_dev *dev); unsigned char drive_info; @@ -119,13 +119,34 @@ extern void zs_kgdb_hook(int tty_num); static void ohare_init(void); -static void init_p2pbridge(void); #ifdef CONFIG_BOOTX_TEXT void pmac_progress(char *s, unsigned short hex); #endif sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; +#ifdef CONFIG_SMP +volatile static long int core99_l2_cache; +void core99_init_l2(void) +{ + int cpu = smp_processor_id(); + + if ( (_get_PVR() >> 16) != 8 && (_get_PVR() >> 16) != 12 ) + return; + + if (cpu == 0){ + core99_l2_cache = _get_L2CR(); + printk("CPU0: L2CR is %lx\n", core99_l2_cache); + } else { + printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR()); + _set_L2CR(0); + _set_L2CR(core99_l2_cache); + printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache); + } +} +#endif /* CONFIG_SMP */ + + __pmac int pmac_get_cpuinfo(char *buffer) @@ -250,7 +271,7 @@ struct device_node *cpu; int *fp; - /* Set loops_per_sec to a half-way reasonable value, + /* Set loops_per_jiffy to a half-way reasonable value, for use until calibrate_delay gets called. */ cpu = find_type_devices("cpu"); if (cpu != 0) { @@ -263,13 +284,13 @@ case 10: /* mach V (604ev5) */ case 12: /* G4 */ case 20: /* 620 */ - loops_per_sec = *fp; + loops_per_jiffy = *fp / HZ; break; default: /* 601, 603, etc. */ - loops_per_sec = *fp / 2; + loops_per_jiffy = *fp / (2*HZ); } } else - loops_per_sec = 50000000; + loops_per_jiffy = 50000000 / HZ; } /* this area has the CPU identification register @@ -278,8 +299,8 @@ __ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY)); ohare_init(); + /* Lookup PCI hosts */ pmac_find_bridges(); - init_p2pbridge(); /* Checks "l2cr-value" property in the registry */ if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) { @@ -303,6 +324,11 @@ ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) ? "enabled" : "disabled"); +#ifdef CONFIG_SMP + /* somewhat of a hack */ + core99_init_l2(); +#endif + #ifdef CONFIG_KGDB zs_kgdb_hook(0); #endif @@ -330,32 +356,6 @@ ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); } -/* - * Tweak the PCI-PCI bridge chip on the blue & white G3s. - */ -static void __init init_p2pbridge(void) -{ - struct device_node *p2pbridge; - unsigned char bus, devfn; - unsigned short val; - - /* XXX it would be better here to identify the specific - PCI-PCI bridge chip we have. */ - if ((p2pbridge = find_devices("pci-bridge")) == 0 - || p2pbridge->parent == NULL - || strcmp(p2pbridge->parent->name, "pci") != 0) - return; - if (pci_device_loc(p2pbridge, &bus, &devfn) < 0) - return; - if (ppc_md.pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) { - printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); - return; - } - val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; - ppc_md.pcibios_write_config_word(bus, devfn, PCI_BRIDGE_CONTROL, val); - ppc_md.pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val); -} - static void __init ohare_init(void) { /* @@ -448,7 +448,7 @@ void __init find_boot_device(void) { -#ifdef CONFIG_SCSI +#if defined(CONFIG_SCSI) && defined(CONFIG_BLK_DEV_SD) if (boot_host != NULL) { boot_dev = sd_find_target(boot_host, boot_target); if (boot_dev != 0) @@ -493,7 +493,9 @@ struct adb_request req; #endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_NVRAM pmac_nvram_update(); +#endif switch (sys_ctrler) { #ifdef CONFIG_ADB_CUDA @@ -509,7 +511,7 @@ pmu_restart(); break; #endif /* CONFIG_ADB_PMU */ - default: + default: ; } } @@ -520,7 +522,9 @@ struct adb_request req; #endif /* CONFIG_ADB_CUDA */ +#ifdef CONFIG_NVRAM pmac_nvram_update(); +#endif switch (sys_ctrler) { #ifdef CONFIG_ADB_CUDA @@ -536,7 +540,7 @@ pmu_shutdown(); break; #endif /* CONFIG_ADB_PMU */ - default: + default: ; } } @@ -566,17 +570,19 @@ int pmac_ide_default_irq(ide_ioreg_t base) { - return 0; -} - #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -extern ide_ioreg_t pmac_ide_get_base(int index); + extern int pmac_ide_get_irq(ide_ioreg_t base); + return pmac_ide_get_irq(base); +#else + return 0; #endif +} ide_ioreg_t pmac_ide_default_io_base(int index) { #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) + extern ide_ioreg_t pmac_ide_get_base(int index); return pmac_ide_get_base(index); #else return 0; @@ -586,7 +592,14 @@ int pmac_ide_check_region(ide_ioreg_t from, unsigned int extent) { - return 0; + /* + * We only do the check_region if `from' looks like a genuine + * I/O port number. If it actually refers to a memory-mapped + * register, it should be OK. + */ + if (from < ~_IO_BASE) + return 0; + return check_region(from, extent); } void @@ -594,24 +607,16 @@ unsigned int extent, const char *name) { + if (from < ~_IO_BASE) + request_region(from, extent, name); } void pmac_ide_release_region(ide_ioreg_t from, unsigned int extent) { -} - -/* Convert the shorts/longs in hd_driveid from little to big endian; - * chars are endian independant, of course, but strings need to be flipped. - * (Despite what it says in drivers/block/ide.h, they come up as little - * endian...) - * - * Changes to linux/hdreg.h may require changes here. */ -void -pmac_ide_fix_driveid(struct hd_driveid *id) -{ - ppc_generic_ide_fix_driveid(id); + if (from < ~_IO_BASE) + release_region(from, extent); } #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) @@ -632,8 +637,6 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - pmac_setup_pci_ptrs(); - /* isa_io_base gets set in pmac_find_bridges */ isa_mem_base = PMAC_ISA_MEM_BASE; pci_dram_offset = PMAC_PCI_DRAM_OFFSET; @@ -646,8 +649,11 @@ ppc_md.get_cpuinfo = pmac_get_cpuinfo; ppc_md.irq_cannonicalize = NULL; ppc_md.init_IRQ = pmac_pic_init; - ppc_md.get_irq = pmac_get_irq; + ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ ppc_md.init = pmac_init2; + + ppc_md.pcibios_fixup = pmac_pcibios_fixup; + ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; ppc_md.restart = pmac_restart; ppc_md.power_off = pmac_power_off; @@ -658,10 +664,6 @@ ppc_md.get_rtc_time = pmac_get_rtc_time; ppc_md.calibrate_decr = pmac_calibrate_decr; - ppc_md.pci_dev_io_base = pmac_pci_dev_io_base; - ppc_md.pci_dev_mem_base = pmac_pci_dev_mem_base; - ppc_md.pci_dev_root_bridge = pmac_pci_dev_root_bridge; - #ifdef CONFIG_VT #ifdef CONFIG_INPUT_ADBHID ppc_md.kbd_init_hw = mac_hid_init_hw; @@ -682,35 +684,33 @@ } #endif /* CONFIG_MAGIC_SYSRQ */ #elif defined(CONFIG_ADB_KEYBOARD) - ppc_md.kbd_setkeycode = mackbd_setkeycode; - ppc_md.kbd_getkeycode = mackbd_getkeycode; - ppc_md.kbd_translate = mackbd_translate; - ppc_md.kbd_unexpected_up = mackbd_unexpected_up; - ppc_md.kbd_leds = mackbd_leds; - ppc_md.kbd_init_hw = mackbd_init_hw; + ppc_md.kbd_setkeycode = mackbd_setkeycode; + ppc_md.kbd_getkeycode = mackbd_getkeycode; + ppc_md.kbd_translate = mackbd_translate; + ppc_md.kbd_unexpected_up = mackbd_unexpected_up; + ppc_md.kbd_leds = mackbd_leds; + ppc_md.kbd_init_hw = mackbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ - ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; + ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; SYSRQ_KEY = 0x69; #endif /* CONFIG_MAGIC_SYSRQ */ #endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */ #endif /* CONFIG_VT */ #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - ppc_ide_md.insw = pmac_ide_insw; - ppc_ide_md.outsw = pmac_ide_outsw; - ppc_ide_md.default_irq = pmac_ide_default_irq; - ppc_ide_md.default_io_base = pmac_ide_default_io_base; - ppc_ide_md.ide_check_region = pmac_ide_check_region; - ppc_ide_md.ide_request_region = pmac_ide_request_region; - ppc_ide_md.ide_release_region = pmac_ide_release_region; - ppc_ide_md.fix_driveid = pmac_ide_fix_driveid; - ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; /* actually too early for this :-( */ -#endif + ppc_ide_md.insw = pmac_ide_insw; + ppc_ide_md.outsw = pmac_ide_outsw; + ppc_ide_md.default_irq = pmac_ide_default_irq; + ppc_ide_md.default_io_base = pmac_ide_default_io_base; + ppc_ide_md.ide_check_region = pmac_ide_check_region; + ppc_ide_md.ide_request_region = pmac_ide_request_region; + ppc_ide_md.ide_release_region = pmac_ide_release_region; + ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; + ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; +#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ #ifdef CONFIG_BOOTX_TEXT ppc_md.progress = pmac_progress; -#endif +#endif /* CONFIG_BOOTX_TEXT */ if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); } @@ -727,5 +727,5 @@ prom_drawstring(s); prom_drawchar('\n'); } -#endif CONFIG_BOOTX_TEXT +#endif /* CONFIG_BOOTX_TEXT */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/pmac_time.c linux.ac/arch/ppc/kernel/pmac_time.c --- linux-2.4.0/arch/ppc/kernel/pmac_time.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/pmac_time.c Mon Dec 18 20:45:24 2000 @@ -114,7 +114,7 @@ + (req.reply[3] << 8) + req.reply[4]; return now - RTC_OFFSET; #endif /* CONFIG_ADB_PMU */ - default: + default: ; } return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/ppc_asm.h linux.ac/arch/ppc/kernel/ppc_asm.h --- linux-2.4.0/arch/ppc/kernel/ppc_asm.h Tue Jun 20 01:59:36 2000 +++ linux.ac/arch/ppc/kernel/ppc_asm.h Mon Dec 18 20:45:33 2000 @@ -66,9 +66,13 @@ #define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n+8,b,base) #define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base) +#ifdef CONFIG_PPC601_SYNC_FIX #define SYNC \ sync; \ isync +#else +#define SYNC +#endif /* * This instruction is not implemented on the PPC 603 or 601; however, on diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/ppc_htab.c linux.ac/arch/ppc/kernel/ppc_htab.c --- linux-2.4.0/arch/ppc/kernel/ppc_htab.c Tue Jun 20 01:59:36 2000 +++ linux.ac/arch/ppc/kernel/ppc_htab.c Mon Dec 18 20:45:33 2000 @@ -555,10 +555,7 @@ break; buffer += len; left -= len; - _set_L2CR(0); _set_L2CR(val); - while ( _get_L2CR() & 0x1 ) - /* wait for invalidate to finish */; } else { p = buf; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/ppc_ksyms.c linux.ac/arch/ppc/kernel/ppc_ksyms.c --- linux-2.4.0/arch/ppc/kernel/ppc_ksyms.c Sun Nov 12 02:23:10 2000 +++ linux.ac/arch/ppc/kernel/ppc_ksyms.c Mon Dec 18 20:45:33 2000 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include #ifdef CONFIG_SMP #include +#include #endif /* CONFIG_SMP */ #include @@ -98,10 +100,6 @@ EXPORT_SYMBOL(ucSystemType); #endif #endif -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_dev_io_base); -EXPORT_SYMBOL(pci_dev_mem_base); -#endif #if !__INLINE_BITOPS EXPORT_SYMBOL(set_bit); @@ -202,6 +200,10 @@ EXPORT_SYMBOL(_read_unlock); EXPORT_SYMBOL(_write_lock); EXPORT_SYMBOL(_write_unlock); +EXPORT_SYMBOL(smp_call_function); +EXPORT_SYMBOL(smp_hw_index); +EXPORT_SYMBOL(smp_num_cpus); +EXPORT_SYMBOL(synchronize_irq); #endif #ifndef CONFIG_MACH_SPECIFIC @@ -247,11 +249,17 @@ EXPORT_SYMBOL(find_phandle); EXPORT_SYMBOL(device_is_compatible); EXPORT_SYMBOL(machine_is_compatible); -EXPORT_SYMBOL(find_pci_device_OFnode); EXPORT_SYMBOL(find_all_nodes); EXPORT_SYMBOL(get_property); -EXPORT_SYMBOL(pci_io_base); -EXPORT_SYMBOL(pci_device_loc); +EXPORT_SYMBOL(pci_bus_io_base); +EXPORT_SYMBOL(pci_bus_io_base_phys); +EXPORT_SYMBOL(pci_bus_mem_base_phys); +EXPORT_SYMBOL(pci_device_to_OF_node); +EXPORT_SYMBOL(pci_device_from_OF_node); +EXPORT_SYMBOL(pci_bus_to_hose); +EXPORT_SYMBOL(pci_resource_to_bus); +EXPORT_SYMBOL(pci_phys_to_bus); +EXPORT_SYMBOL(pci_bus_to_phys); EXPORT_SYMBOL(feature_set); EXPORT_SYMBOL(feature_clear); EXPORT_SYMBOL(feature_test); @@ -286,6 +294,7 @@ EXPORT_SYMBOL(screen_info); #endif +EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(int_control); EXPORT_SYMBOL(timer_interrupt_intercept); EXPORT_SYMBOL(timer_interrupt); @@ -300,6 +309,10 @@ #ifdef CONFIG_XMON EXPORT_SYMBOL(xmon); #endif +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); EXPORT_SYMBOL(down_read_failed); EXPORT_SYMBOL(down_write_failed); @@ -324,6 +337,10 @@ EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); EXPORT_SYMBOL(mmu_context_overflow); +extern long *intercept_table; +extern long *ret_from_intercept; +EXPORT_SYMBOL(intercept_table); +EXPORT_SYMBOL(ret_from_intercept); #ifdef CONFIG_MOL extern ulong mol_interface[]; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/prep_nvram.c linux.ac/arch/ppc/kernel/prep_nvram.c --- linux-2.4.0/arch/ppc/kernel/prep_nvram.c Thu Oct 7 18:17:08 1999 +++ linux.ac/arch/ppc/kernel/prep_nvram.c Mon Dec 18 20:45:33 2000 @@ -16,17 +16,9 @@ #include #include -/* - * Allow for a maximum of 32K of PReP NvRAM data - */ -#define MAX_PREP_NVRAM 0x8000 static char nvramData[MAX_PREP_NVRAM]; static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0]; -#define PREP_NVRAM_AS0 0x74 -#define PREP_NVRAM_AS1 0x75 -#define PREP_NVRAM_DATA 0x77 - unsigned char *rs_pcNvRAM; unsigned char __prep prep_nvram_read_val(int addr) @@ -72,8 +64,8 @@ */ if ( _prep_type == _PREP_Radstone ) rs_pcNvRAM = (unsigned char *)ioremap(_ISA_MEM_BASE+0x00800000, - 32<<10); - request_region(PREP_NVRAM_AS0, 0x8, "PReP NVRAM"); + 32<<10); + /* * The following could fail if the NvRAM were corrupt but * we expect the boot firmware to have checked its checksum diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/prep_pci.c linux.ac/arch/ppc/kernel/prep_pci.c --- linux-2.4.0/arch/ppc/kernel/prep_pci.c Thu Feb 10 03:43:47 2000 +++ linux.ac/arch/ppc/kernel/prep_pci.c Wed Jan 3 17:09:30 2001 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -25,6 +24,7 @@ #include #include "pci.h" +#include "open_pic.h" #define MAX_DEVNR 22 @@ -39,9 +39,6 @@ /* Used for Motorola to store system config register */ static unsigned long *ProcInfo; -extern int chrp_get_irq(struct pt_regs *); -extern void chrp_post_irq(struct pt_regs* regs, int); - /* Tables for known hardware */ /* Motorola PowerStackII - Utah */ @@ -534,128 +531,45 @@ #define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset) #define DEVNO(dev) (dev>>3) -__prep -int -prep_pcibios_read_config_dword (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned int *val) -{ - unsigned long _val; - unsigned long *ptr; - - if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR)) - { - *val = 0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned long *)CFGPTR(dev); - _val = le32_to_cpu(*ptr); - } - *val = _val; - return PCIBIOS_SUCCESSFUL; -} +#define cfg_read(val, addr, type, op) *val = op((type)(addr)) +#define cfg_write(val, addr, type, op) op((type *)(addr), (val)) -__prep -int -prep_pcibios_read_config_word (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned short *val) -{ - unsigned short _val; - unsigned short *ptr; - - if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR)) - { - *val = 0xFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned short *)CFGPTR(dev); - _val = le16_to_cpu(*ptr); - } - *val = _val; - return PCIBIOS_SUCCESSFUL; -} +#define cfg_read_bad(val, size) *val = bad_##size; +#define cfg_write_bad(val, size) -__prep -int -prep_pcibios_read_config_byte (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned char *val) -{ - unsigned char _val; - unsigned char *ptr; - - if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR)) - { - *val = 0xFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned char *)CFGPTR(dev); - _val = *ptr; - } - *val = _val; - return PCIBIOS_SUCCESSFUL; +#define bad_byte 0xff +#define bad_word 0xffff +#define bad_dword 0xffffffffU + +#define PREP_PCI_OP(rw, size, type, op) \ +static int __prep \ +prep_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + if ((dev->bus->number != 0) || (DEVNO(dev->devfn) > MAX_DEVNR)) \ + { \ + cfg_##rw##_bad(val, size) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ + } \ + cfg_##rw(val, CFGPTR(dev->devfn), type, op); \ + return PCIBIOS_SUCCESSFUL; \ } -__prep -int -prep_pcibios_write_config_dword (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned int val) -{ - unsigned long _val; - unsigned long *ptr; - - _val = le32_to_cpu(val); - if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned long *)CFGPTR(dev); - *ptr = _val; - } - return PCIBIOS_SUCCESSFUL; -} - -__prep -int -prep_pcibios_write_config_word (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned short val) -{ - unsigned short _val; - unsigned short *ptr; - - _val = le16_to_cpu(val); - if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned short *)CFGPTR(dev); - *ptr = _val; - } - return PCIBIOS_SUCCESSFUL; -} - -__prep -int -prep_pcibios_write_config_byte (unsigned char bus, - unsigned char dev, unsigned char offset, unsigned char val) -{ - unsigned char _val; - unsigned char *ptr; - - _val = val; - if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR)) - { - return PCIBIOS_DEVICE_NOT_FOUND; - } else - { - ptr = (unsigned char *)CFGPTR(dev); - *ptr = _val; - } - return PCIBIOS_SUCCESSFUL; -} +PREP_PCI_OP(read, byte, u8 *, in_8) +PREP_PCI_OP(read, word, u16 *, in_le16) +PREP_PCI_OP(read, dword, u32 *, in_le32) +PREP_PCI_OP(write, byte, u8, out_8) +PREP_PCI_OP(write, word, u16, out_le16) +PREP_PCI_OP(write, dword, u32, out_le32) + +static struct pci_ops prep_pci_ops = +{ + prep_read_config_byte, + prep_read_config_word, + prep_read_config_dword, + prep_write_config_byte, + prep_write_config_word, + prep_write_config_dword +}; #define MOTOROLA_CPUTYPE_REG 0x800 #define MOTOROLA_BASETYPE_REG 0x803 @@ -685,7 +599,8 @@ #define MOT_HAWK_PRESENT 0x2 int prep_keybd_present = 1; -int MotMPIC = 0; +int MotMPIC; +int mot_multi; int __init raven_init(void) { @@ -695,18 +610,18 @@ /* Check to see if the Raven chip exists. */ if ( _prep_type != _PREP_Motorola) { - OpenPIC = NULL; + OpenPIC_Addr = NULL; return 0; } /* Check to see if this board is a type that might have a Raven. */ if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) { - OpenPIC = NULL; + OpenPIC_Addr = NULL; return 0; } /* Check the first PCI device to see if it is a Raven. */ - pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &devid); + early_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &devid); switch (devid & 0xffff0000) { case MPIC_RAVEN_ID: @@ -716,33 +631,37 @@ MotMPIC = MOT_HAWK_PRESENT; break; default: - OpenPIC = NULL; + OpenPIC_Addr = NULL; return 0; } /* Read the memory base register. */ - pcibios_read_config_dword(0, 0, PCI_BASE_ADDRESS_1, &pci_membase); + early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase); if (pci_membase == 0) { - OpenPIC = NULL; + OpenPIC_Addr = NULL; return 0; } /* Map the Raven MPIC registers to virtual memory. */ - OpenPIC = (struct OpenPIC *)ioremap(pci_membase+0xC0000000, 0x22000); + OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000); OpenPIC_InitSenses = mvme2600_openpic_initsenses; OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses); - ppc_md.get_irq = chrp_get_irq; - ppc_md.post_irq = chrp_post_irq; + ppc_md.get_irq = openpic_get_irq; /* If raven is present on Motorola store the system config register * for later use. */ ProcInfo = (unsigned long *)ioremap(0xfef80400, 4); + /* Indicate to system if this is a multiprocessor board */ + if (!(*ProcInfo & MOT_PROC2_BIT)) { + mot_multi = 1; + } + /* This is a hack. If this is a 2300 or 2400 mot board then there is * no keyboard controller and we have to indicate that. */ @@ -996,7 +915,7 @@ prep_route_pci_interrupts(); printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name); - if (OpenPIC) { + if (OpenPIC_Addr) { /* PCI interrupts are controlled by the OpenPIC */ pci_for_each_dev(dev) { if (dev->bus->number == 0) { @@ -1018,7 +937,12 @@ for ( i = 0 ; i <= 5 ; i++ ) { - if ( dev->resource[i].start > 0x10000000 ) + /* + * Relocate PCI I/O resources if necessary so the + * standard 256MB BAT covers them. + */ + if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) && + (dev->resource[i].start > 0x10000000) ) { printk("Relocating PCI address %lx -> %lx\n", dev->resource[i].start, @@ -1043,49 +967,55 @@ } } -decl_config_access_method(indirect); - void __init -prep_setup_pci_ptrs(void) +prep_find_bridges(void) { - PPC_DEVICE *hostbridge; + struct pci_controller* hose; - printk("PReP architecture\n"); - if ( _prep_type == _PREP_Radstone ) - { - pci_config_address = (unsigned *)0x80000cf8; - pci_config_data = (char *)0x80000cfc; - set_config_access_method(indirect); - } - else - { - hostbridge = residual_find_device(PROCESSORDEVICE, NULL, - BridgeController, PCIBridge, -1, 0); - if (hostbridge && - hostbridge->DeviceId.Interface == PCIBridgeIndirect) { - PnP_TAG_PACKET * pkt; - set_config_access_method(indirect); - pkt = PnP_find_large_vendor_packet( + hose = pcibios_alloc_controller(); + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + hose->pci_mem_offset = PREP_ISA_MEM_BASE; + + printk("PReP architecture\n"); + if ( _prep_type == _PREP_Radstone ) + { + setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc); + } + else + { +#ifdef CONFIG_PREP_RESIDUAL + PPC_DEVICE *hostbridge; + + hostbridge = residual_find_device(PROCESSORDEVICE, NULL, + BridgeController, PCIBridge, -1, 0); + if (hostbridge && + hostbridge->DeviceId.Interface == PCIBridgeIndirect) { + PnP_TAG_PACKET * pkt; + pkt = PnP_find_large_vendor_packet( res->DevicePnPHeap+hostbridge->AllocatedOffset, 3, 0); - if(pkt) + if(pkt) { #define p pkt->L4_Pack.L4_Data.L4_PPCPack - pci_config_address= (unsigned *)ld_le32((unsigned *) p.PPCData); - pci_config_data= (unsigned char *)ld_le32((unsigned *) (p.PPCData+8)); - } + setup_indirect_pci(hose, + ld_le32((unsigned *) (p.PPCData)), + ld_le32((unsigned *) (p.PPCData+8))); + } else { - pci_config_address= (unsigned *) 0x80000cf8; - pci_config_data= (unsigned char *) 0x80000cfc; - } - } + setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc); + } + } else +#endif /* CONFIG_PREP_RESIDUAL */ { - set_config_access_method(prep); - } - - } + hose->ops = &prep_pci_ops; + } + } ppc_md.pcibios_fixup = prep_pcibios_fixup; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/prep_setup.c linux.ac/arch/ppc/kernel/prep_setup.c --- linux-2.4.0/arch/ppc/kernel/prep_setup.c Sun Oct 8 17:33:07 2000 +++ linux.ac/arch/ppc/kernel/prep_setup.c Wed Jan 3 17:09:30 2001 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -48,8 +47,9 @@ #include #include #include - +#include #include + #include "local_irq.h" #include "i8259.h" #include "open_pic.h" @@ -84,7 +84,7 @@ extern void pckbd_init_hw(void); extern unsigned char pckbd_sysrq_xlate[128]; -extern void prep_setup_pci_ptrs(void); +extern void prep_find_bridges(void); extern char saved_command_line[256]; int _prep_type; @@ -108,9 +108,6 @@ extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ extern int rd_image_start; /* starting block # of image */ #endif -#ifdef CONFIG_VGA_CONSOLE -unsigned long vgacon_remap_base; -#endif int __prep prep_get_cpuinfo(char *buffer) @@ -190,7 +187,10 @@ } -no_l2: +no_l2: +#ifndef CONFIG_PREP_RESIDUAL + return len; +#else if ( res->ResidualLength == 0 ) return len; @@ -205,8 +205,8 @@ res->Memories[i].SIMMSize); } len += sprintf(buffer+len,"\n"); - return len; +#endif } void __init @@ -220,6 +220,9 @@ /* init to some ~sane value until calibrate_delay() runs */ loops_per_sec = 50000000; + /* Lookup PCI host bridges */ + prep_find_bridges(); + /* Set up floppy in PS/2 mode */ outb(0x09, SIO_CONFIG_RA); reg = inb(SIO_CONFIG_RD); @@ -341,12 +344,6 @@ #endif /* CONFIG_SOUND_CS4232 */ /*print_residual_device_info();*/ - request_region(0x20,0x20,"pic1"); - request_region(0xa0,0x20,"pic2"); - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); raven_init(); @@ -365,6 +362,7 @@ */ void __init prep_res_calibrate_decr(void) { +#ifdef CONFIG_PREP_RESIDUAL unsigned long freq, divisor=4; freq = res->VitalProductData.ProcessorBusHz; @@ -372,6 +370,7 @@ (freq/divisor)/1000000, (freq/divisor)%1000000); tb_ticks_per_jiffy = freq / HZ / divisor; tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); +#endif } /* @@ -585,15 +584,16 @@ { int len = 0; - /* PREP's without residual data will give incorrect values here */ len += sprintf(len+buffer, "clock\t\t: "); +#ifdef CONFIG_PREP_RESIDUAL if ( res->ResidualLength ) len += sprintf(len+buffer, "%ldMHz\n", (res->VitalProductData.ProcessorHz > 1024) ? res->VitalProductData.ProcessorHz>>20 : res->VitalProductData.ProcessorHz); else +#endif /* CONFIG_PREP_RESIDUAL */ len += sprintf(len+buffer, "???\n"); return len; @@ -640,19 +640,11 @@ { int i; - if (OpenPIC != NULL) { - for ( i = 16 ; i < 36 ; i++ ) - irq_desc[i].handler = &open_pic; - openpic_init(1); - } - - for ( i = 0 ; i < 16 ; i++ ) + if (OpenPIC_Addr != NULL) + openpic_init(1, NUM_8259_INTERRUPTS, 0, -1); + for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) irq_desc[i].handler = &i8259_pic; - i8259_init(); -#ifdef CONFIG_SMP - request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action, - 0, "IPI0", 0); -#endif /* CONFIG_SMP */ + i8259_init(); } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) @@ -708,19 +700,14 @@ unsigned int extent, const char *name) { - request_region(from, extent, name); + request_region(from, extent, name); } void __prep prep_ide_release_region(ide_ioreg_t from, unsigned int extent) { - release_region(from, extent); -} - -void __prep -prep_ide_fix_driveid(struct hd_driveid *id) -{ + release_region(from, extent); } void __init @@ -743,17 +730,52 @@ } #endif +unsigned long *MotSave_SmpIar; +unsigned char *MotSave_CpusState[2]; + +void __init +prep_init2(void) +{ +#ifdef CONFIG_NVRAM + request_region(PREP_NVRAM_AS0, 0x8, "nvram"); +#endif + request_region(0x20,0x20,"pic1"); + request_region(0xa0,0x20,"pic2"); + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); +} + void __init prep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { +#ifdef CONFIG_PREP_RESIDUAL + RESIDUAL *old_res = (RESIDUAL *)(r3 + KERNELBASE); + /* make a copy of residual data */ if ( r3 ) { memcpy((void *)res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL)); + + /* These need to be saved for the Motorola Prep + * MVME4600 and Dual MTX boards. + */ + MotSave_SmpIar = &old_res->VitalProductData.SmpIar; + MotSave_CpusState[0] = &old_res->Cpus[0].CpuState; + MotSave_CpusState[1] = &old_res->Cpus[1].CpuState; } +#endif + /* Copy cmd_line parameters */ + if ( r6) + { + *(char *)(r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6 + KERNELBASE)); + } + isa_io_base = PREP_ISA_IO_BASE; isa_mem_base = PREP_ISA_MEM_BASE; pci_dram_offset = PREP_PCI_DRAM_OFFSET; @@ -762,6 +784,7 @@ DMA_MODE_WRITE = 0x48; /* figure out what kind of prep workstation we are */ +#ifdef CONFIG_PREP_RESIDUAL if ( res->ResidualLength != 0 ) { if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) @@ -779,12 +802,11 @@ _prep_type = _PREP_Motorola; } else /* assume motorola if no residual (netboot?) */ +#endif { _prep_type = _PREP_Motorola; } - prep_setup_pci_ptrs(); - ppc_md.setup_arch = prep_setup_arch; ppc_md.setup_residual = prep_setup_residual; ppc_md.get_cpuinfo = prep_get_cpuinfo; @@ -792,7 +814,7 @@ ppc_md.init_IRQ = prep_init_IRQ; /* this gets changed later on if we have an OpenPIC -- Cort */ ppc_md.get_irq = prep_get_irq; - ppc_md.init = NULL; + ppc_md.init = prep_init2; ppc_md.restart = prep_restart; ppc_md.power_off = prep_power_off; @@ -845,7 +867,7 @@ ppc_ide_md.ide_check_region = prep_ide_check_region; ppc_ide_md.ide_request_region = prep_ide_request_region; ppc_ide_md.ide_release_region = prep_ide_release_region; - ppc_ide_md.fix_driveid = prep_ide_fix_driveid; + ppc_ide_md.fix_driveid = NULL; ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports; #endif ppc_ide_md.io_base = _IO_BASE; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/proc_rtas.c linux.ac/arch/ppc/kernel/proc_rtas.c --- linux-2.4.0/arch/ppc/kernel/proc_rtas.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/kernel/proc_rtas.c Thu Dec 21 21:33:08 2000 @@ -0,0 +1,786 @@ +/* + * arch/ppc/kernel/proc_rtas.c + * Copyright (C) 2000 Tilmann Bitterberg + * (tilmann@bitterberg.de) + * + * RTAS (Runtime Abstraction Services) stuff + * Intention is to provide a clean user interface + * to use the RTAS. + * + * TODO: + * Split off a header file and maybe move it to a different + * location. Write Documentation on what the /proc/rtas/ entries + * actually do. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* for ppc_md */ +#include + +/* Token for Sensors */ +#define KEY_SWITCH 0x0001 +#define ENCLOSURE_SWITCH 0x0002 +#define THERMAL_SENSOR 0x0003 +#define LID_STATUS 0x0004 +#define POWER_SOURCE 0x0005 +#define BATTERY_VOLTAGE 0x0006 +#define BATTERY_REMAINING 0x0007 +#define BATTERY_PERCENTAGE 0x0008 +#define EPOW_SENSOR 0x0009 +#define BATTERY_CYCLESTATE 0x000a +#define BATTERY_CHARGING 0x000b + +/* IBM specific sensors */ +#define IBM_SURVEILLANCE 0x2328 /* 9000 */ +#define IBM_FANRPM 0x2329 /* 9001 */ +#define IBM_VOLTAGE 0x232a /* 9002 */ +#define IBM_DRCONNECTOR 0x232b /* 9003 */ +#define IBM_POWERSUPPLY 0x232c /* 9004 */ +#define IBM_INTQUEUE 0x232d /* 9005 */ + +/* Status return values */ +#define SENSOR_CRITICAL_HIGH 13 +#define SENSOR_WARNING_HIGH 12 +#define SENSOR_NORMAL 11 +#define SENSOR_WARNING_LOW 10 +#define SENSOR_CRITICAL_LOW 9 +#define SENSOR_SUCCESS 0 +#define SENSOR_HW_ERROR -1 +#define SENSOR_BUSY -2 +#define SENSOR_NOT_EXIST -3 +#define SENSOR_DR_ENTITY -9000 + +/* Location Codes */ +#define LOC_SCSI_DEV_ADDR 'A' +#define LOC_SCSI_DEV_LOC 'B' +#define LOC_CPU 'C' +#define LOC_DISKETTE 'D' +#define LOC_ETHERNET 'E' +#define LOC_FAN 'F' +#define LOC_GRAPHICS 'G' +/* reserved / not used 'H' */ +#define LOC_IO_ADAPTER 'I' +/* reserved / not used 'J' */ +#define LOC_KEYBOARD 'K' +#define LOC_LCD 'L' +#define LOC_MEMORY 'M' +#define LOC_NV_MEMORY 'N' +#define LOC_MOUSE 'O' +#define LOC_PLANAR 'P' +#define LOC_OTHER_IO 'Q' +#define LOC_PARALLEL 'R' +#define LOC_SERIAL 'S' +#define LOC_DEAD_RING 'T' +#define LOC_RACKMOUNTED 'U' /* for _u_nit is rack mounted */ +#define LOC_VOLTAGE 'V' +#define LOC_SWITCH_ADAPTER 'W' +#define LOC_OTHER 'X' +#define LOC_FIRMWARE 'Y' +#define LOC_SCSI 'Z' + +/* Tokens for indicators */ +#define TONE_FREQUENCY 0x0001 /* 0 - 1000 (HZ)*/ +#define TONE_VOLUME 0x0002 /* 0 - 100 (%) */ +#define SYSTEM_POWER_STATE 0x0003 +#define WARNING_LIGHT 0x0004 +#define DISK_ACTIVITY_LIGHT 0x0005 +#define HEX_DISPLAY_UNIT 0x0006 +#define BATTERY_WARNING_TIME 0x0007 +#define CONDITION_CYCLE_REQUEST 0x0008 +#define SURVEILLANCE_INDICATOR 0x2328 /* 9000 */ +#define DR_ACTION 0x2329 /* 9001 */ +#define DR_INDICATOR 0x232a /* 9002 */ +/* 9003 - 9004: Vendor specific */ +#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */ +/* 9006 - 9999: Vendor specific */ + +/* other */ +#define MAX_SENSORS 17 /* I only know of 17 sensors */ +#define MAX_LINELENGTH 256 +#define SENSOR_PREFIX "ibm,sensor-" +#define cel_to_fahr(x) ((x*9/5)+32) + + +/* Globals */ +static struct proc_dir_entry *proc_rtas; +static struct rtas_sensors sensors; +static struct device_node *rtas; +static unsigned long power_on_time = 0; /* Save the time the user set */ +static char progress_led[MAX_LINELENGTH]; + +static unsigned long rtas_tone_frequency = 1000; +static unsigned long rtas_tone_volume = 0; + +/* ****************STRUCTS******************************************* */ +struct individual_sensor { + unsigned int token; + unsigned int quant; +}; + +struct rtas_sensors { + struct individual_sensor sensor[MAX_SENSORS]; + unsigned int quant; +}; + +/* ****************************************************************** */ +/* Declarations */ +static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off, + int count, int *eof, void *data); +static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_progress_read(struct file * file, char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf, + size_t count, loff_t *ppos); + +static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, + size_t count, loff_t *ppos); +static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, + size_t count, loff_t *ppos); + +struct file_operations ppc_rtas_poweron_operations = { + read: ppc_rtas_poweron_read, + write: ppc_rtas_poweron_write +}; +struct file_operations ppc_rtas_progress_operations = { + read: ppc_rtas_progress_read, + write: ppc_rtas_progress_write +}; + +struct file_operations ppc_rtas_clock_operations = { + read: ppc_rtas_clock_read, + write: ppc_rtas_clock_write +}; + +struct file_operations ppc_rtas_tone_freq_operations = { + read: ppc_rtas_tone_freq_read, + write: ppc_rtas_tone_freq_write +}; +struct file_operations ppc_rtas_tone_volume_operations = { + read: ppc_rtas_tone_volume_read, + write: ppc_rtas_tone_volume_write +}; + +int ppc_rtas_find_all_sensors (void); +int ppc_rtas_process_sensor(struct individual_sensor s, int state, + int error, char * buf); +char * ppc_rtas_process_error(int error); +int get_location_code(struct individual_sensor s, char * buf); +int check_location_string (char *c, char * buf); +int check_location (char *c, int idx, char * buf); + +/* ****************************************************************** */ +/* MAIN */ +/* ****************************************************************** */ +void proc_rtas_init(void) +{ + struct proc_dir_entry *entry; + + rtas = find_devices("rtas"); + if ((rtas == 0) || (_machine != _MACH_chrp)) { + return; + } + + proc_rtas = proc_mkdir("rtas", 0); + if (proc_rtas == 0) + return; + + /* /proc/rtas entries */ + + entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas); + if (entry) entry->proc_fops = &ppc_rtas_progress_operations; + + entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); + if (entry) entry->proc_fops = &ppc_rtas_clock_operations; + + entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); + if (entry) entry->proc_fops = &ppc_rtas_poweron_operations; + + create_proc_read_entry("sensors", S_IRUGO, proc_rtas, + ppc_rtas_sensor_read, NULL); + + entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); + if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations; + + entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); + if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations; + create_proc_read_entry("errors", S_IRUGO, proc_rtas, + ppc_rtas_errorlog_read, NULL); +} + +/* ****************************************************************** */ +/* POWER-ON-TIME */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + struct rtc_time tm; + unsigned long nowtime; + char *dest; + int error; + + nowtime = simple_strtoul(buf, &dest, 10); + if (*dest != '\0' && *dest != '\n') { + printk("ppc_rtas_poweron_write: Invalid time\n"); + return count; + } + power_on_time = nowtime; /* save the time */ + + to_tm(nowtime, &tm); + + error = call_rtas("set-time-for-power-on", 7, 1, NULL, + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); + if (error != 0) + printk(KERN_WARNING "error: setting poweron time returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + int n; + if (power_on_time == 0) + n = sprintf(buf, "Power on time not set\n"); + else + n = sprintf(buf, "%lu\n", power_on_time); + + if (*ppos >= strlen(buf)) + return 0; + if (n > strlen(buf) - *ppos) + n = strlen(buf) - *ppos; + if (n > count) + n = count; + *ppos += n; + return n; +} + +/* ****************************************************************** */ +/* PROGRESS */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long hex; + + strcpy(progress_led, buf); /* save the string */ + /* Lets see if the user passed hexdigits */ + hex = simple_strtoul(buf, NULL, 10); + + ppc_md.progress ((char *)buf, hex); + return count; + + /* clear the line */ /* ppc_md.progress(" ", 0xffff);*/ +} +/* ****************************************************************** */ +static ssize_t ppc_rtas_progress_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + int n = 0; + if (progress_led != NULL) + n = sprintf (buf, "%s\n", progress_led); + if (*ppos >= strlen(buf)) + return 0; + if (n > strlen(buf) - *ppos) + n = strlen(buf) - *ppos; + if (n > count) + n = count; + *ppos += n; + return n; +} + +/* ****************************************************************** */ +/* CLOCK */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + struct rtc_time tm; + unsigned long nowtime; + char *dest; + int error; + + nowtime = simple_strtoul(buf, &dest, 10); + if (*dest != '\0' && *dest != '\n') { + printk("ppc_rtas_clock_write: Invalid time\n"); + return count; + } + + to_tm(nowtime, &tm); + error = call_rtas("set-time-of-day", 7, 1, NULL, + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, 0); + if (error != 0) + printk(KERN_WARNING "error: setting the clock returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + unsigned int year, mon, day, hour, min, sec; + unsigned long *ret = kmalloc(4*8, GFP_KERNEL); + int n, error; + + error = call_rtas("get-time-of-day", 0, 8, ret); + + year = ret[0]; mon = ret[1]; day = ret[2]; + hour = ret[3]; min = ret[4]; sec = ret[5]; + + if (error != 0){ + printk(KERN_WARNING "error: reading the clock returned: %s\n", + ppc_rtas_process_error(error)); + n = sprintf (buf, "0"); + } else { + n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec)); + } + kfree(ret); + + if (*ppos >= strlen(buf)) + return 0; + if (n > strlen(buf) - *ppos) + n = strlen(buf) - *ppos; + if (n > count) + n = count; + *ppos += n; + return n; +} + +/* ****************************************************************** */ +/* SENSOR STUFF */ +/* ****************************************************************** */ +static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off, + int count, int *eof, void *data) +{ + int i,j,n; + unsigned long ret; + int state, error; + char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */ + + if (count < 0) + return -EINVAL; + + n = sprintf ( buffer , "RTAS (RunTime Abstraction Services) Sensor Information\n"); + n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n"); + n += sprintf ( buffer+n, "********************************************************\n"); + + if (ppc_rtas_find_all_sensors() != 0) { + n += sprintf ( buffer+n, "\nNo sensors are available\n"); + goto return_string; + } + + for (i=0; i= 0) { + error = call_rtas("get-sensor-state", 2, 2, &ret, + sensors.sensor[i].token, sensors.sensor[i].quant-j); + state = (int) ret; + n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n ); + n += sprintf (buffer+n, "\n"); + j--; + } /* while */ + } /* for */ + +return_string: + if (off >= strlen(buffer)) { + *eof = 1; + return 0; + } + if (n > strlen(buffer) - off) + n = strlen(buffer) - off; + if (n > count) + n = count; + else + *eof = 1; + memcpy(buf, buffer + off, n); + *start = buf; + return n; +} + +/* ****************************************************************** */ + +int ppc_rtas_find_all_sensors (void) +{ + unsigned long *utmp; + int len, i, j; + + utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len); + if (utmp == NULL) { + printk (KERN_ERR "error: could not get rtas-sensors\n"); + return 1; + } + + sensors.quant = len / 8; /* int + int */ + + for (i=0, j=0; j= llen) pos=0; + } + return n; +} +/* ****************************************************************** */ +/* INDICATORS - Tone Frequency */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long freq; + char *dest; + int error; + freq = simple_strtoul(buf, &dest, 10); + if (*dest != '\0' && *dest != '\n') { + printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n"); + return count; + } + if (freq < 0) freq = 0; + rtas_tone_frequency = freq; /* save it for later */ + error = call_rtas("set-indicator", 3, 1, NULL, + TONE_FREQUENCY, 0, freq); + if (error != 0) + printk(KERN_WARNING "error: setting tone frequency returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + int n; + n = sprintf(buf, "%lu\n", rtas_tone_frequency); + + if (*ppos >= strlen(buf)) + return 0; + if (n > strlen(buf) - *ppos) + n = strlen(buf) - *ppos; + if (n > count) + n = count; + *ppos += n; + return n; +} +/* ****************************************************************** */ +/* INDICATORS - Tone Volume */ +/* ****************************************************************** */ +static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + unsigned long volume; + char *dest; + int error; + volume = simple_strtoul(buf, &dest, 10); + if (*dest != '\0' && *dest != '\n') { + printk("ppc_rtas_tone_volume_write: Invalid tone volume\n"); + return count; + } + if (volume < 0) volume = 0; + if (volume > 100) volume = 100; + + rtas_tone_volume = volume; /* save it for later */ + error = call_rtas("set-indicator", 3, 1, NULL, + TONE_VOLUME, 0, volume); + if (error != 0) + printk(KERN_WARNING "error: setting tone volume returned: %s\n", + ppc_rtas_process_error(error)); + return count; +} +/* ****************************************************************** */ +static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, + size_t count, loff_t *ppos) +{ + int n; + n = sprintf(buf, "%lu\n", rtas_tone_volume); + + if (*ppos >= strlen(buf)) + return 0; + if (n > strlen(buf) - *ppos) + n = strlen(buf) - *ppos; + if (n > count) + n = count; + *ppos += n; + return n; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/process.c linux.ac/arch/ppc/kernel/process.c --- linux-2.4.0/arch/ppc/kernel/process.c Sun Nov 12 02:14:38 2000 +++ linux.ac/arch/ppc/kernel/process.c Wed Jan 3 17:09:30 2001 @@ -251,13 +251,15 @@ { int i; - printk("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx\n", - regs->nip, regs->xer, regs->link, regs,regs->trap); + printk("NIP: %08lX XER: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx\n", + regs->nip, regs->xer, regs->link, regs->gpr[1], regs,regs->trap); 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); + if (regs->trap == 0x300 || regs->trap == 0x600) + printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); printk("TASK = %p[%d] '%s' ", current, current->pid, current->comm); printk("Last syscall: %ld ", current->thread.last_syscall); @@ -285,7 +287,7 @@ printk("\n"); } } -out: +out: ; } void exit_thread(void) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/prom.c linux.ac/arch/ppc/kernel/prom.c --- linux-2.4.0/arch/ppc/kernel/prom.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/prom.c Wed Jan 3 17:09:30 2001 @@ -32,6 +32,8 @@ #include #include #include +/* for openpic_to_irq */ +#include "open_pic.h" #ifdef CONFIG_FB #include @@ -95,26 +97,28 @@ #define FB_MAX 8 #endif char *prom_display_paths[FB_MAX] __initdata = { 0, }; -unsigned int prom_num_displays = 0; -char *of_stdout_device = 0; - -prom_entry prom = 0; -ihandle prom_chosen = 0, prom_stdout = 0, prom_disp_node = 0; +unsigned int prom_num_displays __initdata = 0; +char *of_stdout_device __initdata = 0; +ihandle prom_disp_node __initdata = 0; + +prom_entry prom __initdata = 0; +ihandle prom_chosen __initdata = 0; +ihandle prom_stdout __initdata = 0; extern char *klimit; -char *bootpath = 0; -char *bootdevice = 0; +char *bootpath; +char *bootdevice; -unsigned int rtas_data = 0; /* physical pointer */ -unsigned int rtas_entry = 0; /* physical pointer */ -unsigned int rtas_size = 0; -unsigned int old_rtas = 0; +unsigned int rtas_data; /* physical pointer */ +unsigned int rtas_entry; /* physical pointer */ +unsigned int rtas_size; +unsigned int old_rtas; /* Set for a newworld machine */ -int use_of_interrupt_tree = 0; -int pmac_newworld = 0; +int use_of_interrupt_tree; +int pmac_newworld; -static struct device_node *allnodes = 0; +static struct device_node *allnodes; #ifdef CONFIG_BOOTX_TEXT @@ -134,13 +138,12 @@ static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb); static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb); -/* We want those in data, not BSS */ -static long g_loc_X = 0; -static long g_loc_Y = 0; -static long g_max_loc_X = 0; -static long g_max_loc_Y = 0; +static int g_loc_X; +static int g_loc_Y; +static int g_max_loc_X; +static int g_max_loc_Y; -unsigned long disp_BAT[2] = {0, 0}; +unsigned long disp_BAT[2] __initdata = {0, 0}; #define cmapsz (16*256) @@ -173,10 +176,10 @@ void phys_call_rtas(int, int, int, ...); extern char cmd_line[512]; /* XXX */ -boot_infos_t *boot_infos = 0; /* init it so it's in data segment not bss */ +boot_infos_t *boot_infos; #ifdef CONFIG_BOOTX_TEXT -boot_infos_t *disp_bi = 0; -boot_infos_t fake_bi = {0,}; +boot_infos_t *disp_bi; +boot_infos_t fake_bi; #endif unsigned long dev_tree_size; @@ -195,10 +198,6 @@ * OF calls should be done within prom_init(), and prom_init() * and all routines called within it must be careful to relocate * references as necessary. - * - * Note that the bss is cleared *after* prom_init runs, so we have - * to make sure that any static or extern variables it accesses - * are put in the data segment. */ #define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) #define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) @@ -618,6 +617,11 @@ char *p, *d; int prom_version = 0; unsigned long phys; + extern char __bss_start, _end; + + /* First zero the BSS -- use memset, some arches don't have + * caches on yet */ + memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); /* Default */ phys = offset + KERNELBASE; @@ -948,34 +952,6 @@ if ((int) call_prom(RELOC("package-to-path"), 3, 1, node, path, 255) < 0) continue; - prom_print(RELOC("opening display ")); - prom_print(path); - ih = call_prom(RELOC("open"), 1, 1, path); - if (ih == 0 || ih == (ihandle) -1) { - prom_print(RELOC("... failed\n")); - continue; - } - prom_print(RELOC("... ok\n")); - - if (RELOC(prom_disp_node) == 0) - RELOC(prom_disp_node) = node; - - /* Setup a useable color table when the appropriate - * method is available. Should update this to set-colors */ - for (i = 0; i < 32; i++) - if (prom_set_color(ih, i, RELOC(default_colors)[i*3], - RELOC(default_colors)[i*3+1], - RELOC(default_colors)[i*3+2]) != 0) - break; - -#ifdef CONFIG_FB - for (i = 0; i < LINUX_LOGO_COLORS; i++) - if (prom_set_color(ih, i + 32, - RELOC(linux_logo_red)[i], - RELOC(linux_logo_green)[i], - RELOC(linux_logo_blue)[i]) != 0) - break; -#endif /* CONFIG_FB */ /* * If this display is the device that OF is using for stdout, @@ -990,9 +966,44 @@ = RELOC(prom_display_paths[i-1]); } RELOC(prom_display_paths[i]) = PTRUNRELOC(path); + if (i == 0) + RELOC(prom_disp_node) = node; if (RELOC(prom_num_displays) >= FB_MAX) break; } + + /* + * Open the first display and set its colormap. + */ + if (RELOC(prom_num_displays) > 0) { + path = PTRRELOC(RELOC(prom_display_paths[0])); + prom_print(RELOC("opening display ")); + prom_print(path); + ih = call_prom(RELOC("open"), 1, 1, path); + if (ih == 0 || ih == (ihandle) -1) { + prom_print(RELOC("... failed\n")); + } else { + prom_print(RELOC("... ok\n")); + + /* Setup a useable color table when the appropriate + * method is available. Should update this to set-colors */ + for (i = 0; i < 32; i++) + if (prom_set_color(ih, i, RELOC(default_colors)[i*3], + RELOC(default_colors)[i*3+1], + RELOC(default_colors)[i*3+2]) != 0) + break; + +#ifdef CONFIG_FB + for (i = 0; i < LINUX_LOGO_COLORS; i++) + if (prom_set_color(ih, i + 32, + RELOC(linux_logo_red)[i], + RELOC(linux_logo_green)[i], + RELOC(linux_logo_blue)[i]) != 0) + break; +#endif /* CONFIG_FB */ + } + } + return ALIGN(mem); } @@ -1277,7 +1288,7 @@ if (!strcmp(np->name, "display")) np->name = get_property(np, "compatible", 0); - if (!strcmp(np->name, "device-tree")) + if (np->parent == NULL) ifunc = interpret_root_props; else if (np->type == 0) ifunc = NULL; @@ -1370,7 +1381,7 @@ np->intrs[i].line = *interrupts++; if (cvt_irq) np->intrs[i].line = openpic_to_irq(np->intrs[i].line); - np->intrs[i].sense = 0; + np->intrs[i].sense = 1; if (isize > 1) np->intrs[i].sense = *interrupts++; for (j=2; j= 0; ++i) { if (imp->addr.a_hi == devfn) { np->intrs[np->n_intrs].line = imp->intr; - np->intrs[np->n_intrs].sense = 0; /* FIXME */ + np->intrs[np->n_intrs].sense = 1; /* FIXME */ ++np->n_intrs; } imp = (struct pci_intr_map *)(((unsigned int)imp) @@ -1561,7 +1572,7 @@ mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; - np->intrs[i].sense = 0; + np->intrs[i].sense = 1; } } @@ -1614,7 +1625,7 @@ mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; - np->intrs[i].sense = 0; + np->intrs[i].sense = 1; } } @@ -1675,7 +1686,7 @@ if (keylargo) np->intrs[i].sense = *ip++; else - np->intrs[i].sense = 0; + np->intrs[i].sense = 1; } } else { /* CHRP machines */ @@ -1771,7 +1782,7 @@ mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; - np->intrs[i].sense = 0; + np->intrs[i].sense = 1; } } @@ -1779,6 +1790,30 @@ } /* + * Work out the sense (active-low level / active-high edge) + * of each interrupt from the device tree. + */ +void __init +prom_get_irq_senses(unsigned char *senses, int off, int max) +{ + struct device_node *np; + int i, j; + + /* default to level-triggered */ + memset(senses, 1, max - off); + if (!use_of_interrupt_tree) + return; + + for (np = allnodes; np != 0; np = np->allnext) { + for (j = 0; j < np->n_intrs; j++) { + i = np->intrs[j].line; + if (i >= off && i < max) + senses[i-off] = np->intrs[j].sense; + } + } +} + +/* * Construct and return a list of the device_nodes with a given name. */ __openfirmware @@ -1818,39 +1853,6 @@ return head; } -/* Finds a device node given its PCI bus number, device number - * and function number - */ -__openfirmware -struct device_node * -find_pci_device_OFnode(unsigned char bus, unsigned char dev_fn) -{ - struct device_node* np; - unsigned int *reg; - int l; - - for (np = allnodes; np != 0; np = np->allnext) { - int in_macio = 0; - struct device_node* parent = np->parent; - while(parent) { - char *pname = (char *)get_property(parent, "name", &l); - if (pname && strcmp(pname, "mac-io") == 0) { - in_macio = 1; - break; - } - parent = parent->parent; - } - if (in_macio) - continue; - reg = (unsigned int *) get_property(np, "reg", &l); - if (reg == 0 || l < sizeof(struct reg_property)) - continue; - if (((reg[0] >> 8) & 0xff) == dev_fn && ((reg[0] >> 16) & 0xff) == bus) - break; - } - return np; -} - /* * Returns all nodes linked together */ @@ -1981,6 +1983,21 @@ return pp->value; } return 0; +} + +/* + * Add a property to a node + */ +__openfirmware +void +prom_add_property(struct device_node* np, struct property* prop) +{ + struct property **next = &np->properties; + + prop->next = NULL; + while (*next) + next = &(*next)->next; + *next = prop; } #if 0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/setup.c linux.ac/arch/ppc/kernel/setup.c --- linux-2.4.0/arch/ppc/kernel/setup.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/setup.c Fri Dec 22 16:37:58 2000 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,10 @@ unsigned long SYSRQ_KEY; #endif /* CONFIG_MAGIC_SYSRQ */ +#ifdef CONFIG_VGA_CONSOLE +unsigned long vgacon_remap_base; +#endif + struct machdep_calls ppc_md; /* @@ -377,9 +382,9 @@ len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min); len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n", - (CD(loops_per_sec)+2500)/500000, - (CD(loops_per_sec)+2500)/5000 % 100); - bogosum += CD(loops_per_sec); + (CD(loops_per_jiffy)+2500)/(500000/HZ), + (CD(loops_per_jiffy)+2500)/(5000/HZ) % 100); + bogosum += CD(loops_per_jiffy); } #ifdef CONFIG_SMP @@ -673,13 +678,14 @@ void __init ppc_init(void) { /* clear the progress line */ - if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); + if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); if (ppc_md.init != NULL) { ppc_md.init(); } } +/* Warning, IO base is not yet inited */ void __init setup_arch(char **cmdline_p) { extern int panic_timeout; @@ -688,7 +694,7 @@ extern void do_init_bootmem(void); /* so udelay does something sensible, assume <= 1000 bogomips */ - loops_per_sec = 500000000; + loops_per_jiffy = 500000000 / HZ; #ifdef CONFIG_ALL_PPC feature_init(); @@ -743,10 +749,34 @@ ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); +#ifdef CONFIG_PCI + /* We create the "pci-OF-bus-map" property now so it appear in the + * /proc device tree + */ + if (have_of) { + struct property* of_prop; + + of_prop = (struct property*)alloc_bootmem(sizeof(struct property) + 256); + if (of_prop && find_path_device("/")) { + memset(of_prop, -1, sizeof(struct property) + 256); + of_prop->name = "pci-OF-bus-map"; + of_prop->length = 256; + of_prop->value = (unsigned char *)&of_prop[1]; + prom_add_property(find_path_device("/"), of_prop); + } + } +#endif /* CONFIG_PCI */ + paging_init(); sort_exception_table(); } +/* Convert the shorts/longs in hd_driveid from little to big endian; + * chars are endian independant, of course, but strings need to be flipped. + * (Despite what it says in drivers/block/ide.h, they come up as little + * endian...) + * + * Changes to linux/hdreg.h may require changes here. */ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) { int i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/smp.c linux.ac/arch/ppc/kernel/smp.c --- linux-2.4.0/arch/ppc/kernel/smp.c Mon Oct 16 20:58:51 2000 +++ linux.ac/arch/ppc/kernel/smp.c Wed Jan 3 17:09:30 2001 @@ -1,6 +1,4 @@ /* - * $Id: smp.c,v 1.68 1999/09/17 19:38:05 cort Exp $ - * * Smp support for ppc. * * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great @@ -8,8 +6,11 @@ * * Copyright (C) 1999 Cort Dougan * - * Support for PReP (Motorola MTX/MVME) SMP by Troy Benjegerdes - * (troy@microux.com, hozer@drgw.net) + * Support for PReP (Motorola MTX/MVME) and Macintosh G4 SMP + * by Troy Benjegerdes (hozer@drgw.net) + * + * Support for DayStar quad CPU cards + * Copyright (C) XLR8, Inc. 1994-2000 */ #include @@ -23,7 +24,6 @@ #define __KERNEL_SYSCALLS__ #include #include -#include #include #include @@ -38,46 +38,97 @@ #include #include #include - +#include +#include #include + #include "open_pic.h" int smp_threads_ready; volatile int smp_commenced; int smp_num_cpus = 1; +int smp_tb_synchronized; struct cpuinfo_PPC cpu_data[NR_CPUS]; struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 }; -volatile unsigned char active_kernel_processor = NO_PROC_ID; /* Processor holding kernel spinlock */ -volatile unsigned long ipi_count; +atomic_t ipi_recv; +atomic_t ipi_sent; spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; cycles_t cacheflush_time; +static int max_cpus __initdata = NR_CPUS; -/* this has to go in the data section because it is accessed from prom_init */ int smp_hw_index[NR_CPUS]; /* all cpu mappings are 1-1 -- Cort */ volatile unsigned long cpu_callin_map[NR_CPUS]; +#define TB_SYNC_PASSES 4 +volatile unsigned long __initdata tb_sync_flag = 0; +volatile unsigned long __initdata tb_offset = 0; + int start_secondary(void *); extern int cpu_idle(void *unused); -u_int openpic_read(volatile u_int *addr); void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); +extern void __secondary_start_psurge(void); +extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ +extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ + +/* Addresses for powersurge registers */ +#define HAMMERHEAD_BASE 0xf8000000 +#define HHEAD_CONFIG 0x90 +#define HHEAD_SEC_INTR 0xc0 + /* register for interrupting the primary processor on the powersurge */ /* N.B. this is actually the ethernet ROM! */ -#define PSURGE_PRI_INTR 0xf3019000 -/* register for interrupting the secondary processor on the powersurge */ -#define PSURGE_SEC_INTR 0xf80000c0 +#define PSURGE_PRI_INTR 0xf3019000 + /* register for storing the start address for the secondary processor */ -#define PSURGE_START 0xf2800000 -/* virtual addresses for the above */ -volatile u32 *psurge_pri_intr; -volatile u32 *psurge_sec_intr; -volatile u32 *psurge_start; +/* N.B. this is the PCI config space address register for the 1st bridge */ +#define PSURGE_START 0xf2800000 + +/* Daystar/XLR8 4-CPU card */ +#define PSURGE_QUAD_REG_ADDR 0xf8800000 -/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. */ +#define PSURGE_QUAD_IRQ_SET 0 +#define PSURGE_QUAD_IRQ_CLR 1 +#define PSURGE_QUAD_IRQ_PRIMARY 2 +#define PSURGE_QUAD_CKSTOP_CTL 3 +#define PSURGE_QUAD_PRIMARY_ARB 4 +#define PSURGE_QUAD_BOARD_ID 6 +#define PSURGE_QUAD_WHICH_CPU 7 +#define PSURGE_QUAD_CKSTOP_RDBK 8 +#define PSURGE_QUAD_RESET_CTL 11 + +#define PSURGE_QUAD_OUT(r, v) (out_8((quad_base+((r)<<2)+1), (v))) +#define PSURGE_QUAD_IN(r) (in_8((quad_base+((r)<<2)+1)) & 0x0f) +#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) +#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) + +/* virtual addresses for the above */ +static volatile u8 *hhead_base; +static volatile u8 *quad_base; +static volatile u32 *psurge_pri_intr; +static volatile u8 *psurge_sec_intr; +static volatile u32 *psurge_start; + +/* what sort of powersurge board we have */ +static int psurge_type; + +/* values for psurge_type */ +#define PSURGE_DUAL 0 +#define PSURGE_QUAD_OKEE 1 +#define PSURGE_QUAD_COTTON 2 +#define PSURGE_QUAD_ICEGRASS 3 + +/* l2 cache stuff for dual G4 macs */ +extern void core99_init_l2(void); + +/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. + * + * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up + * in /proc/interrupts will be wrong!!! --Troy */ #define PPC_MSG_CALL_FUNCTION 0 #define PPC_MSG_RESCHEDULE 1 #define PPC_MSG_INVALIDATE_TLB 2 @@ -85,10 +136,615 @@ static inline void set_tb(unsigned int upper, unsigned int lower) { + mtspr(SPRN_TBWL, 0); mtspr(SPRN_TBWU, upper); mtspr(SPRN_TBWL, lower); } +/* + * Set and clear IPIs for powersurge. + */ +static inline void psurge_set_ipi(int cpu) +{ + if (cpu == 0) + in_be32(psurge_pri_intr); + else if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, 0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); +} + +static inline void psurge_clr_ipi(int cpu) +{ + if (cpu > 0) { + if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, ~0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); + } +} + +/* + * On powersurge (old SMP powermac architecture) we don't have + * separate IPIs for separate messages like openpic does. Instead + * we have a bitmap for each processor, where a 1 bit means that + * the corresponding message is pending for that processor. + * Ideally each cpu's entry would be in a different cache line. + * -- paulus. + */ +static unsigned long psurge_smp_message[NR_CPUS]; + +void psurge_smp_message_recv(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int msg; + + /* clear interrupt */ + psurge_clr_ipi(cpu); + + if (smp_num_cpus < 2) + return; + + /* make sure there is a message there */ + for (msg = 0; msg < 4; msg++) + if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) + smp_message_recv(msg, regs); +} + +void +psurge_primary_intr(int irq, void *d, struct pt_regs *regs) +{ + psurge_smp_message_recv(regs); +} + +static void +smp_psurge_message_pass(int target, int msg, unsigned long data, int wait) +{ + int i; + + if (smp_num_cpus < 2) + return; + + for (i = 0; i < smp_num_cpus; i++) { + if (target == MSG_ALL + || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) + || target == i) { + set_bit(msg, &psurge_smp_message[i]); + psurge_set_ipi(i); + } + } +} + +/* + * Determine a quad card presence. We read the board ID register, we + * for the data bus to change to something else, and we read it again. + * It it's stable, then the register probably exist (ugh !) + */ +static int __init psurge_quad_probe(void) +{ + int type; + unsigned int i; + + type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); + if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS + || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + + /* looks OK, try a slightly more rigorous test */ + /* bogus is not necessarily cacheline-aligned, + though I don't suppose that really matters. -- paulus */ + for (i = 0; i < 100; i++) { + volatile u32 bogus[8]; + bogus[(0+i)%8] = 0x00000000; + bogus[(1+i)%8] = 0x55555555; + bogus[(2+i)%8] = 0xFFFFFFFF; + bogus[(3+i)%8] = 0xAAAAAAAA; + bogus[(4+i)%8] = 0x33333333; + bogus[(5+i)%8] = 0xCCCCCCCC; + bogus[(6+i)%8] = 0xCCCCCCCC; + bogus[(7+i)%8] = 0x33333333; + wmb(); + asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); + mb(); + if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + } + return type; +} + +static void __init psurge_quad_init(void) +{ + int procbits; + + if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); + procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); + if (psurge_type == PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + else + PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); + mdelay(33); + out_8(psurge_sec_intr, ~0); + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + if (psurge_type != PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); + PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); + PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); + mdelay(33); + PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); +} + +static int __init smp_psurge_probe(void) +{ + int i, ncpus; + + /* We don't do SMP on the PPC601 -- paulus */ + if ((_get_PVR() >> 16) == 1) + return 1; + + /* + * The powersurge cpu board can be used in the generation + * of powermacs that have a socket for an upgradeable cpu card, + * including the 7500, 8500, 9500, 9600. + * The device tree doesn't tell you if you have 2 cpus because + * OF doesn't know anything about the 2nd processor. + * Instead we look for magic bits in magic registers, + * in the hammerhead memory controller in the case of the + * dual-cpu powersurge board. -- paulus. + */ + if (find_devices("hammerhead") == NULL) + return 1; + + hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); + quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); + psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; + + psurge_type = psurge_quad_probe(); + if (psurge_type != PSURGE_DUAL) { + psurge_quad_init(); + /* I believe we could "count" CPUs by counting 1 bits + * in procbits on a quad board. For now, we assume 4, + * non-present CPUs will just be seen as "stuck". + * (hope they are the higher-numbered ones -- paulus) + */ + ncpus = 4; + } else { + iounmap((void *) quad_base); + if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { + /* not a dual-cpu card */ + iounmap((void *) hhead_base); + return 1; + } + ncpus = 2; + } + + psurge_start = ioremap(PSURGE_START, 4); + psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); + + /* this is not actually strictly necessary -- paulus. */ + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + + if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); + + return ncpus; +} + +static void __init smp_psurge_kick_cpu(int nr) +{ + void (*start)(void) = __secondary_start_psurge; + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); + + /* setup entry point of secondary processor */ + switch (nr) { + case 2: + start = __secondary_start_psurge2; + break; + case 3: + start = __secondary_start_psurge3; + break; + } + + out_be32(psurge_start, __pa(start)); + mb(); + + psurge_set_ipi(nr); + udelay(10); + psurge_clr_ipi(nr); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); +} + +/* + * With the dual-cpu powersurge board, the decrementers and timebases + * of both cpus are frozen after the secondary cpu is started up, + * until we give the secondary cpu another interrupt. This routine + * uses this to get the timebases synchronized. + * -- paulus. + */ +static void __init psurge_dual_sync_tb(int cpu_nr) +{ + static volatile int sec_tb_reset = 0; + int t; + + set_dec(tb_ticks_per_jiffy); + set_tb(0, 0); + last_jiffy_stamp(cpu_nr) = 0; + + if (cpu_nr > 0) { + mb(); + sec_tb_reset = 1; + return; + } + + /* wait for the secondary to have reset its TB before proceeding */ + for (t = 10000000; t > 0 && !sec_tb_reset; --t) + ; + + /* now interrupt the secondary, starting both TBs */ + psurge_set_ipi(1); + + smp_tb_synchronized = 1; +} + +static void +smp_psurge_setup_cpu(int cpu_nr) +{ + + if (cpu_nr == 0) { + if (smp_num_cpus < 2) + return; + /* reset the entry point so if we get another intr we won't + * try to startup again */ + out_be32(psurge_start, 0x100); + if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0)) + printk(KERN_ERR "Couldn't get primary IPI interrupt"); + } + + if (psurge_type == PSURGE_DUAL) + psurge_dual_sync_tb(cpu_nr); +} + + +static void +smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) +{ + /* make sure we're sending something that translates to an IPI */ + if ( msg > 0x3 ){ + printk("SMP %d: smp_message_pass: unknown msg %d\n", + smp_processor_id(), msg); + return; + } + switch ( target ) + { + case MSG_ALL: + openpic_cause_IPI(msg, 0xffffffff); + break; + case MSG_ALL_BUT_SELF: + openpic_cause_IPI(msg, + 0xffffffff & ~(1 << smp_processor_id())); + break; + default: + openpic_cause_IPI(msg, 1< 1) { + openpic_request_IPIs(); + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + } + + return ncpus; +} + +static void +smp_core99_kick_cpu(int nr) +{ + unsigned long save_int; + unsigned long flags; + volatile unsigned long *vector + = ((volatile unsigned long *)(KERNELBASE+0x500)); + + if (nr != 1) + return; + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); + + local_irq_save(flags); + local_irq_disable(); + + /* Save EE vector */ + save_int = *vector; + + /* Setup fake EE vector that does + * b __secondary_start_psurge - KERNELBASE + */ + *vector = 0x48000002 + + ((unsigned long)__secondary_start_psurge - KERNELBASE); + + /* flush data cache and inval instruction cache */ + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + /* Put some life in our friend */ + feature_core99_kick_cpu1(); + + /* FIXME: We wait a bit for the CPU to take the exception, I should + * instead wait for the entry code to set something for me. Well, + * ideally, all that crap will be done in prom.c and the CPU left + * in a RAM-based wait loop like CHRP. + */ + mdelay(1); + + /* Restore our exception vector */ + *vector = save_int; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + if (ppc_md.progress) ppc_md.progress("smp_core99_probe done", 0x347); +} + +static void +smp_core99_setup_cpu(int cpu_nr) +{ + /* Setup openpic */ + do_openpic_setup_cpu(); + + /* Setup L2 */ + if (cpu_nr != 0) + core99_init_l2(); + else + if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); +} + +static int +smp_chrp_probe(void) +{ + extern unsigned long smp_chrp_cpu_nr; + + if (smp_chrp_cpu_nr > 1) + openpic_request_IPIs(); + + return smp_chrp_cpu_nr; +} + +static void +smp_chrp_kick_cpu(int nr) +{ + *(unsigned long *)KERNELBASE = nr; + asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); +} + +static void +smp_chrp_setup_cpu(int cpu_nr) +{ + static atomic_t ready = ATOMIC_INIT(1); + static volatile int frozen = 0; + + if (cpu_nr == 0) { + /* wait for all the others */ + while (atomic_read(&ready) < smp_num_cpus) + barrier(); + atomic_set(&ready, 1); + /* freeze the timebase */ + call_rtas("freeze-time-base", 0, 1, NULL); + mb(); + frozen = 1; + /* XXX assumes this is not a 601 */ + set_tb(0, 0); + last_jiffy_stamp(0) = 0; + while (atomic_read(&ready) < smp_num_cpus) + barrier(); + /* thaw the timebase again */ + call_rtas("thaw-time-base", 0, 1, NULL); + mb(); + frozen = 0; + smp_tb_synchronized = 1; + } else { + atomic_inc(&ready); + while (!frozen) + barrier(); + set_tb(0, 0); + last_jiffy_stamp(0) = 0; + mb(); + atomic_inc(&ready); + while (frozen) + barrier(); + } + + if (OpenPIC_Addr) + do_openpic_setup_cpu(); +} + +#ifdef CONFIG_POWER4 +static void +smp_xics_message_pass(int target, int msg, unsigned long data, int wait) +{ + /* for now, only do reschedule messages + since we only have one IPI */ + if (msg != PPC_MSG_RESCHEDULE) + return; + for (i = 0; i < smp_num_cpus; ++i) { + if (target == MSG_ALL || target == i + || (target == MSG_ALL_BUT_SELF + && i != smp_processor_id())) + xics_cause_IPI(i); + } +} + +static int +smp_xics_probe(void) +{ + return smp_chrp_cpu_nr; +} + +static void +smp_xics_setup_cpu(int cpu_nr) +{ + if (cpu_nr > 0) + xics_setup_cpu(); +} +#endif /* CONFIG_POWER4 */ + +static int +smp_prep_probe(void) +{ + extern int mot_multi; + + if (mot_multi) { + openpic_request_IPIs(); + smp_hw_index[1] = 1; + return 2; + } + + return 1; +} + +static void +smp_prep_kick_cpu(int nr) +{ + extern unsigned long *MotSave_SmpIar; + extern unsigned char *MotSave_CpusState[2]; + + *MotSave_SmpIar = (unsigned long)__secondary_start_psurge - KERNELBASE; + *MotSave_CpusState[1] = CPU_GOOD; + printk("CPU1 reset, waiting\n"); +} + +static void +smp_prep_setup_cpu(int cpu_nr) +{ + if (OpenPIC_Addr) + do_openpic_setup_cpu(); +} + +#ifdef CONFIG_GEMINI +static int +smp_gemini_probe(void) +{ + int i, nr; + + nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; + if (nr == 0) + nr = 4; + + if (nr > 1) { + openpic_request_IPIs(); + for (i = 1; i < nr; ++i) + smp_hw_index[i] = i; + } + + return nr; +} + +static void +smp_gemini_kick_cpu(int nr) +{ + openpic_init_processor( 1< 0) + gemini_init_l2(); +} +#endif /* CONFIG_GEMINI */ + + +static struct smp_ops_t { + void (*message_pass)(int target, int msg, unsigned long data, int wait); + int (*probe)(void); + void (*kick_cpu)(int nr); + void (*setup_cpu)(int nr); + +} *smp_ops; + +#define smp_message_pass(t,m,d,w) \ + do { if (smp_ops) \ + atomic_inc(&ipi_sent); \ + smp_ops->message_pass((t),(m),(d),(w)); \ + } while(0) + + +/* PowerSurge-style Macs */ +static struct smp_ops_t psurge_smp_ops = { + smp_psurge_message_pass, + smp_psurge_probe, + smp_psurge_kick_cpu, + smp_psurge_setup_cpu, +}; + +/* Core99 Macs (dual G4s) */ +static struct smp_ops_t core99_smp_ops = { + smp_openpic_message_pass, + smp_core99_probe, + smp_core99_kick_cpu, + smp_core99_setup_cpu, +}; + +/* CHRP with openpic */ +static struct smp_ops_t chrp_smp_ops = { + smp_openpic_message_pass, + smp_chrp_probe, + smp_chrp_kick_cpu, + smp_chrp_setup_cpu, +}; + +#ifdef CONFIG_POWER4 +/* CHRP with new XICS interrupt controller */ +static struct smp_ops_t xics_smp_ops = { + smp_xics_message_pass, + smp_xics_probe, + smp_chrp_kick_cpu, + smp_xics_setup_cpu, +}; +#endif /* CONFIG_POWER4 */ + +/* PReP (MTX) */ +static struct smp_ops_t prep_smp_ops = { + smp_openpic_message_pass, + smp_prep_probe, + smp_prep_kick_cpu, + smp_prep_setup_cpu, +}; + +#ifdef CONFIG_GEMINI +/* Gemini */ +static struct smp_ops_t gemini_smp_ops = { + smp_openpic_message_pass, + smp_gemini_probe, + smp_gemini_kick_cpu, + smp_gemini_setup_cpu, +}; +#endif /* CONFIG_GEMINI */ + +/* + * Common functions + */ + + void smp_local_timer_interrupt(struct pt_regs * regs) { int cpu = smp_processor_id(); @@ -101,7 +757,7 @@ void smp_message_recv(int msg, struct pt_regs *regs) { - ipi_count++; + atomic_inc(&ipi_recv); switch( msg ) { case PPC_MSG_CALL_FUNCTION: @@ -126,47 +782,6 @@ } /* - * As it is now, if we're sending two message at the same time - * we have race conditions on Pmac. The PowerSurge doesn't easily - * allow us to send IPI messages so we put the messages in - * smp_message[]. - * - * This is because don't have several IPI's on the PowerSurge even though - * we do on the chrp. It would be nice to use actual IPI's such as with - * openpic rather than this. - * -- Cort - */ -int pmac_smp_message[NR_CPUS]; -void pmac_smp_message_recv(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int msg; - - /* clear interrupt */ - if (cpu == 1) - out_be32(psurge_sec_intr, ~0); - - if (smp_num_cpus < 2) - return; - - /* make sure there is a message there */ - msg = pmac_smp_message[cpu]; - if (msg == 0) - return; - - /* reset message */ - pmac_smp_message[cpu] = 0; - - smp_message_recv(msg - 1, regs); -} - -void -pmac_primary_intr(int irq, void *d, struct pt_regs *regs) -{ - pmac_smp_message_recv(regs); -} - -/* * 750's don't broadcast tlb invalidates so * we have to emulate that behavior. * -- Cort @@ -220,7 +835,7 @@ */ static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; -static volatile struct call_data_struct { +static struct call_data_struct { void (*func) (void *info); void *info; atomic_t started; @@ -317,87 +932,9 @@ atomic_inc(&call_data->finished); } -void smp_message_pass(int target, int msg, unsigned long data, int wait) -{ - if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) ) - return; - - switch (_machine) { - case _MACH_Pmac: - /* - * IPI's on the Pmac are a hack but without reasonable - * IPI hardware SMP on Pmac is a hack. - * - * We assume here that the msg is not -1. If it is, - * the recipient won't know the message was destined - * for it. -- Cort - */ - if (smp_processor_id() == 0) { - /* primary cpu */ - if (target == 1 || target == MSG_ALL_BUT_SELF - || target == MSG_ALL) { - pmac_smp_message[1] = msg + 1; - /* interrupt secondary processor */ - out_be32(psurge_sec_intr, ~0); - out_be32(psurge_sec_intr, 0); - } - } else { - /* secondary cpu */ - if (target == 0 || target == MSG_ALL_BUT_SELF - || target == MSG_ALL) { - pmac_smp_message[0] = msg + 1; - /* interrupt primary processor */ - in_be32(psurge_pri_intr); - } - } - if (target == smp_processor_id() || target == MSG_ALL) { - /* sending a message to ourself */ - /* XXX maybe we shouldn't do this if ints are off */ - smp_message_recv(msg, NULL); - } - break; - case _MACH_chrp: - case _MACH_prep: - case _MACH_gemini: -#ifndef CONFIG_POWER4 - /* make sure we're sending something that translates to an IPI */ - if ( msg > 0x3 ) - break; - switch ( target ) - { - case MSG_ALL: - openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff); - break; - case MSG_ALL_BUT_SELF: - openpic_cause_IPI(smp_processor_id(), msg, - 0xffffffff & ~(1 << smp_processor_id())); - break; - default: - openpic_cause_IPI(smp_processor_id(), msg, 1<processor = 0; init_idle(); @@ -427,41 +963,45 @@ */ cacheflush_time = 5 * 1024; - if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_gemini)) ) - { - printk("SMP not supported on this machine.\n"); - return; - } - - switch ( _machine ) - { + /* To be later replaced by some arch-specific routine */ + switch(_machine) { case _MACH_Pmac: - /* assume powersurge board - 2 processors -- Cort */ - cpu_nr = 2; - psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); - psurge_sec_intr = ioremap(PSURGE_SEC_INTR, 4); - psurge_start = ioremap(PSURGE_START, 4); + /* Check for Core99 */ + if (find_devices("uni-n")) + smp_ops = &core99_smp_ops; + else + smp_ops = &psurge_smp_ops; break; case _MACH_chrp: - if (OpenPIC) - for ( i = 0; i < 4 ; i++ ) - openpic_enable_IPI(i); - cpu_nr = smp_chrp_cpu_nr; +#ifndef CONFIG_POWER4 + smp_ops = &chrp_smp_ops; +#else + smp_ops = &xics_smp_ops; +#endif /* CONFIG_POWER4 */ break; + case _MACH_prep: + smp_ops = &prep_smp_ops; + break; +#ifdef CONFIG_GEMINI case _MACH_gemini: - for ( i = 0; i < 4 ; i++ ) - openpic_enable_IPI(i); - cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2; - cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr; + smp_ops = &gemini_smp_ops; break; +#endif /* CONFIG_GEMINI */ + default: + printk("SMP not supported on this machine.\n"); + return; } + + /* Probe arch for CPUs */ + cpu_nr = smp_ops->probe(); /* * only check for cpus we know exist. We keep the callin map * with cpus at the bottom -- Cort */ - for ( i = 1 ; i < cpu_nr; i++ ) - { + if (cpu_nr > max_cpus) + cpu_nr = max_cpus; + for (i = 1; i < cpu_nr; i++) { int c; struct pt_regs regs; @@ -487,25 +1027,7 @@ asm volatile("sync"); /* wake up cpus */ - switch ( _machine ) - { - case _MACH_Pmac: - /* setup entry point of secondary processor */ - out_be32(psurge_start, __pa(__secondary_start_psurge)); - /* interrupt secondary to begin executing code */ - out_be32(psurge_sec_intr, ~0); - udelay(1); - out_be32(psurge_sec_intr, 0); - break; - case _MACH_chrp: - *(unsigned long *)KERNELBASE = i; - asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); - break; - case _MACH_gemini: - openpic_init_processor( 1<kick_cpu(i); /* * wait to see if the cpu made a callin (is actually up). @@ -517,40 +1039,100 @@ if ( cpu_callin_map[i] ) { + char buf[32]; + sprintf(buf, "found cpu %d", i); + if (ppc_md.progress) ppc_md.progress(buf, 0x350+i); printk("Processor %d found.\n", i); smp_num_cpus++; } else { + char buf[32]; + sprintf(buf, "didn't find cpu %d", i); + if (ppc_md.progress) ppc_md.progress(buf, 0x360+i); printk("Processor %d is stuck.\n", i); } } - if (OpenPIC && (_machine & (_MACH_gemini|_MACH_chrp|_MACH_prep))) - do_openpic_setup_cpu(); + /* Setup CPU 0 last (important) */ + smp_ops->setup_cpu(0); +} - if ( _machine == _MACH_Pmac ) - { - /* reset the entry point so if we get another intr we won't - * try to startup again */ - out_be32(psurge_start, 0x100); - if (request_irq(30, pmac_primary_intr, 0, "primary IPI", 0)) - printk(KERN_ERR "Couldn't get primary IPI interrupt"); - /* - * The decrementers of both cpus are frozen at this point - * until we give the secondary cpu another interrupt. - * We set them both to decrementer_count and then send - * the interrupt. This should get the decrementers - * synchronized. - * -- paulus. - */ - set_dec(tb_ticks_per_jiffy); - if ((_get_PVR() >> 16) != 1) { - set_tb(0, 0); /* set timebase if not 601 */ - last_jiffy_stamp(0) = 0; +void __init smp_software_tb_sync(int cpu) +{ +#define PASSES 4 /* 4 passes.. */ + int pass; + int i, j; + + /* stop - start will be the number of timebase ticks it takes for cpu0 + * to send a message to all others and the first reponse to show up. + * + * ASSUMPTION: this time is similiar for all cpus + * ASSUMPTION: the time to send a one-way message is ping/2 + */ + register unsigned long start = 0; + register unsigned long stop = 0; + register unsigned long temp = 0; + + if (smp_num_cpus < 2) + return; + + set_tb(0, 0); + + /* multiple passes to get in l1 cache.. */ + for (pass = 2; pass < 2+PASSES; pass++){ + if (cpu == 0){ + mb(); + for (i = j = 1; i < smp_num_cpus; i++, j++){ + /* skip stuck cpus */ + while (!cpu_callin_map[j]) + ++j; + while (cpu_callin_map[j] != pass) + barrier(); + } + mb(); + tb_sync_flag = pass; + start = get_tbl(); /* start timing */ + while (tb_sync_flag) + mb(); + stop = get_tbl(); /* end timing */ + /* theoretically, the divisor should be 2, but + * I get better results on my dual mtx. someone + * please report results on other smp machines.. + */ + tb_offset = (stop-start)/4; + mb(); + tb_sync_flag = pass; + udelay(10); + mb(); + tb_sync_flag = 0; + mb(); + set_tb(0,0); + mb(); + } else { + cpu_callin_map[cpu] = pass; + mb(); + while (!tb_sync_flag) + mb(); /* wait for cpu0 */ + mb(); + tb_sync_flag = 0; /* send response for timing */ + mb(); + while (!tb_sync_flag) + mb(); + temp = tb_offset; /* make sure offset is loaded */ + while (tb_sync_flag) + mb(); + set_tb(0,temp); /* now, set the timebase */ + mb(); } - out_be32(psurge_sec_intr, ~0); - udelay(1); - out_be32(psurge_sec_intr, 0); } + if (cpu == 0) { + smp_tb_synchronized = 1; + printk("smp_software_tb_sync: %d passes, final offset: %ld\n", + PASSES, tb_offset); + } + /* so time.c doesn't get confused */ + set_dec(tb_ticks_per_jiffy); + last_jiffy_stamp(cpu) = 0; + cpu_callin_map[cpu] = 1; } void __init smp_commence(void) @@ -558,8 +1140,48 @@ /* * Lets the callin's below out of their loop. */ + if (ppc_md.progress) ppc_md.progress("smp_commence", 0x370); wmb(); smp_commenced = 1; + /* if the smp_ops->setup_cpu function has not already synched the + * timebases with a nicer hardware-based method, do so now + * + * I am open to suggestions for improvements to this method + * -- Troy + * + * NOTE: if you are debugging, set smp_tb_synchronized for now + * since if this code runs pretty early and needs all cpus that + * reported in in smp_callin_map to be working + * + * NOTE2: this code doesn't seem to work on > 2 cpus. -- paulus + */ + if (!smp_tb_synchronized) { + unsigned long flags; + __save_and_cli(flags); + smp_software_tb_sync(0); + __restore_flags(flags); + } +} + +void __init smp_callin(void) +{ + int cpu = current->processor; + + smp_store_cpu_info(cpu); + set_dec(tb_ticks_per_jiffy); + cpu_callin_map[cpu] = 1; + + smp_ops->setup_cpu(cpu); + + init_idle(); + + while(!smp_commenced) + barrier(); + /* see smp_commence for more info */ + if (!smp_tb_synchronized){ + smp_software_tb_sync(cpu); + } + __sti(); } /* intel needs this */ @@ -576,37 +1198,6 @@ return cpu_idle(NULL); } -void __init smp_callin(void) -{ - smp_store_cpu_info(current->processor); - set_dec(tb_ticks_per_jiffy); - if (_machine == _MACH_Pmac && (_get_PVR() >> 16) != 1) { - set_tb(0, 0); /* set timebase if not 601 */ - last_jiffy_stamp(current->processor) = 0; - } - init_idle(); - cpu_callin_map[current->processor] = 1; - -#ifndef CONFIG_POWER4 - /* - * Each processor has to do this and this is the best - * place to stick it for now. - * -- Cort - */ - if (OpenPIC && _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep)) - do_openpic_setup_cpu(); -#else - xics_setup_cpu(); -#endif /* CONFIG_POWER4 */ -#ifdef CONFIG_GEMINI - if ( _machine == _MACH_gemini ) - gemini_init_l2(); -#endif - while(!smp_commenced) - barrier(); - __sti(); -} - void __init smp_setup(char *str, int *ints) { } @@ -624,3 +1215,11 @@ c->loops_per_sec = loops_per_sec; c->pvr = _get_PVR(); } + +static int __init maxcpus(char *str) +{ + get_option(&str, &max_cpus); + return 1; +} + +__setup("maxcpus=", maxcpus); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/time.c linux.ac/arch/ppc/kernel/time.c --- linux-2.4.0/arch/ppc/kernel/time.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/time.c Mon Dec 18 20:45:53 2000 @@ -67,7 +67,12 @@ #include -void smp_local_timer_interrupt(struct pt_regs *); +#ifdef CONFIG_SMP +extern void smp_local_timer_interrupt(struct pt_regs *); +extern int smp_tb_synchronized; +#endif /* CONFIG_SMP */ + +extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); /* keep track of when we need to update the rtc */ time_t last_rtc_update; @@ -97,6 +102,36 @@ return delta; } +extern unsigned long prof_cpu_mask; +extern unsigned int * prof_buffer; +extern unsigned long prof_len; +extern unsigned long prof_shift; +extern char _stext; + +static inline void ppc_do_profile (unsigned long nip) +{ + if (!prof_buffer) + return; + + /* + * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. + * (default is all CPUs.) + */ + if (!((1<>= prof_shift; + /* + * Don't ignore out-of-bounds EIP values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (nip > prof_len-1) + nip = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[nip]); +} + /* * timer_interrupt - gets called when the decrementer overflows, * with interrupts disabled. @@ -110,6 +145,9 @@ hardirq_enter(cpu); + if (!user_mode(regs)) + ppc_do_profile(instruction_pointer(regs)); + do { jiffy_stamp += tb_ticks_per_jiffy; if (smp_processor_id()) continue; @@ -151,7 +189,7 @@ #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); -#endif +#endif /* CONFIG_SMP */ if (ppc_md.heartbeat && !ppc_md.heartbeat_count--) ppc_md.heartbeat(); @@ -176,7 +214,7 @@ /* As long as timebases are not in sync, gettimeofday can only * have jiffy resolution on SMP. */ - if (_machine != _MACH_Pmac) + if (!smp_tb_synchronized) delta = 0; #endif /* CONFIG_SMP */ lost_ticks = jiffies - wall_jiffies; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/kernel/traps.c linux.ac/arch/ppc/kernel/traps.c --- linux-2.4.0/arch/ppc/kernel/traps.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/kernel/traps.c Wed Jan 3 17:09:30 2001 @@ -65,21 +65,37 @@ void (*debugger_fault_handler)(struct pt_regs *regs); #endif #endif + /* * Trap & Exception support */ + +spinlock_t oops_lock = SPIN_LOCK_UNLOCKED; + +void die(const char * str, struct pt_regs * fp, long err) +{ + console_verbose(); + spin_lock_irq(&oops_lock); + printk("Oops: %s, sig: %ld\n", str, err); + show_regs(fp); + print_backtrace((unsigned long *)fp->gpr[1]); + spin_unlock_irq(&oops_lock); + /* do_exit() should take care of panic'ing from an interrupt + * context so we don't handle it here + */ + do_exit(err); +} + void _exception(int signr, struct pt_regs *regs) { if (!user_mode(regs)) { - show_regs(regs); #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) debugger(regs); #endif - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Exception in kernel pc %lx signal %d",regs->nip,signr); + die("Exception in kernel mode", regs, signr); } force_sig(signr, current); } @@ -98,7 +114,7 @@ #if defined(CONFIG_8xx) && defined(CONFIG_PCI) /* the qspan pci read routines can cause machine checks -- Cort */ - bad_page_fault(regs, regs->dar); + bad_page_fault(regs, regs->dar, SIGBUS); return; #endif #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) @@ -151,12 +167,10 @@ default: printk("Unknown values in msr\n"); } - show_regs(regs); #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) debugger(regs); #endif - print_backtrace((unsigned long *)regs->gpr[1]); - panic("machine check"); + die("machine check", regs, SIGBUS); } void @@ -337,12 +351,10 @@ int errcode; if (!user_mode(regs)) { - show_regs(regs); #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) debugger(regs); #endif - print_backtrace((unsigned long *)regs->gpr[1]); - panic("Kernel Mode Software FPU Emulation"); + die("Kernel Mode Software FPU Emulation", regs, SIGFPE); } #ifdef CONFIG_MATH_EMULATION diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/lib/Makefile linux.ac/arch/ppc/lib/Makefile --- linux-2.4.0/arch/ppc/lib/Makefile Fri Dec 29 22:07:20 2000 +++ linux.ac/arch/ppc/lib/Makefile Wed Jan 3 17:09:30 2001 @@ -9,6 +9,6 @@ obj-y := checksum.o string.o strcase.o -obj-$(CONFIG_SMP) := locks.o +obj-$(CONFIG_SMP) += locks.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/lib/locks.c linux.ac/arch/ppc/lib/locks.c --- linux-2.4.0/arch/ppc/lib/locks.c Thu Oct 7 18:17:08 1999 +++ linux.ac/arch/ppc/lib/locks.c Wed Jan 3 17:09:30 2001 @@ -58,8 +58,9 @@ { #ifdef DEBUG_LOCKS if ( !lp->lock ) - printk("_spin_unlock(%p): no lock cpu %d %s/%d\n", lp, - smp_processor_id(),current->comm,current->pid); + printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n", + lp, smp_processor_id(), __builtin_return_address(0), + current->comm, current->pid); if ( lp->owner_cpu != smp_processor_id() ) printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n", lp, smp_processor_id(), (int)lp->owner_cpu, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/mm/fault.c linux.ac/arch/ppc/mm/fault.c --- linux-2.4.0/arch/ppc/mm/fault.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/mm/fault.c Wed Jan 3 17:09:39 2001 @@ -48,7 +48,7 @@ unsigned int probingmem = 0; extern void die_if_kernel(char *, struct pt_regs *, long); -void bad_page_fault(struct pt_regs *, unsigned long); +void bad_page_fault(struct pt_regs *, unsigned long, int sig); void do_page_fault(struct pt_regs *, unsigned long, unsigned long); /* @@ -96,7 +96,7 @@ #endif /* CONFIG_XMON || CONFIG_KGDB */ if (in_interrupt() || mm == NULL) { - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGSEGV); return; } down(&mm->mmap_sem); @@ -182,7 +182,7 @@ return; } - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGSEGV); return; /* @@ -194,7 +194,7 @@ printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGKILL); return; do_sigbus: @@ -205,7 +205,7 @@ info.si_addr = (void *)address; force_sig_info (SIGBUS, &info, current); if (!user_mode(regs)) - bad_page_fault(regs, address); + bad_page_fault(regs, address, SIGBUS); } /* @@ -214,8 +214,10 @@ * in traps.c. */ void -bad_page_fault(struct pt_regs *regs, unsigned long address) +bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) { + extern void die(const char *,struct pt_regs *,long); + unsigned long fixup; /* Are we prepared to handle this fault? */ @@ -225,14 +227,11 @@ } /* kernel has accessed a bad area */ - show_regs(regs); #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) if (debugger_kernel_faults) debugger(regs); #endif - print_backtrace( (unsigned long *)regs->gpr[1] ); - panic("kernel access of bad area pc %lx lr %lx address %lX tsk %s/%d", - regs->nip,regs->link,address,current->comm,current->pid); + die("kernel access of bad area", regs, sig); } #ifdef CONFIG_8xx diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/mm/init.c linux.ac/arch/ppc/mm/init.c --- linux-2.4.0/arch/ppc/mm/init.c Wed Nov 29 06:43:39 2000 +++ linux.ac/arch/ppc/mm/init.c Wed Jan 3 17:09:39 2001 @@ -532,6 +532,8 @@ * 0xd0000000 on 64-bit machines. */ flush_hash_segments(0xd, 0xffffff); #else + /* this could cause problems on SMP with nobats -- paulus */ + /* XXX no hash_table_lock? interesting -- paulus */ __clear_user(Hash, Hash_size); _tlbia(); #ifdef CONFIG_SMP @@ -548,6 +550,27 @@ void local_flush_tlb_mm(struct mm_struct *mm) { + if (mm->context == 0) { + /* don't try to reassign a new context to the kernel */ + /* + * This could cause problems on SMP if we aren't using + * the BATs (e.g. on POWER4 or if the nobats option is used). + * The problem scenario is that one cpu is doing + * flush_hash_page or similar when another cpu clears + * out the HPTEs which map the flush_hash_page text + * and the hash table. hash_page will then deadlock. + * We need some way to have "protected" HPTEs or else + * do all hash-table manipulation with the MMU off. + * -- paulus. + */ +#ifdef CONFIG_PPC64BRIDGE + flush_hash_segments(0xd, 0xf); +#else + flush_hash_segments(0xc, 0xf); +#endif CONFIG_PPC64BRIDGE + _tlbia(); + return; + } mm->context = NO_CONTEXT; if (mm == current->mm) activate_mm(mm, mm); @@ -581,16 +604,18 @@ { start &= PAGE_MASK; - if (end - start > 20 * PAGE_SIZE) - { - flush_tlb_mm(mm); - return; + if (mm->context != 0) { + if (end > TASK_SIZE) + end = TASK_SIZE; + if (end - start > 20 * PAGE_SIZE) { + flush_tlb_mm(mm); + return; + } } - for (; start < end && start < TASK_SIZE; start += PAGE_SIZE) - { + for (; start < end; start += PAGE_SIZE) flush_hash_page(mm->context, start); - } + #ifdef CONFIG_SMP smp_send_tlb_invalidate(0); #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/xmon/start.c linux.ac/arch/ppc/xmon/start.c --- linux-2.4.0/arch/ppc/xmon/start.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/xmon/start.c Wed Jan 3 17:09:39 2001 @@ -14,6 +14,10 @@ #include #include #include +#include +#ifdef CONFIG_SMP +#include +#endif static volatile unsigned char *sccc, *sccd; unsigned long TXRDY, RXRDY; @@ -22,10 +26,10 @@ extern void prom_drawstring(const char *str); static int xmon_expect(const char *str, unsigned int timeout); -static int console = 0; -static int use_screen = 1; /* default */ -static int via_modem = 0; -static int xmon_use_sccb = 0; +static int console; +static int use_screen; +static int via_modem = 1; +static int xmon_use_sccb; static struct device_node *macio_node; #define TB_SPEED 25000000 @@ -53,28 +57,32 @@ use_screen = 0; - if ( _machine == _MACH_Pmac ) - { + if (_machine == _MACH_Pmac) { struct device_node *np; unsigned long addr; #ifdef CONFIG_BOOTX_TEXT extern boot_infos_t *disp_bi; + /* see if there is a keyboard in the device tree + with a parent of type "adb" */ + for (np = find_devices("keyboard"); np; np = np->next) + if (np->parent && np->parent->type + && strcmp(np->parent->type, "adb") == 0) + break; + /* needs to be hacked if xmon_printk is to be used from within find_via_pmu() */ #ifdef CONFIG_ADB_PMU - if (!via_modem && disp_bi && find_via_pmu()) { - prom_drawstring("xmon uses screen and keyboard\n"); + if (np != NULL && disp_bi && find_via_pmu()) use_screen = 1; - } #endif #ifdef CONFIG_ADB_CUDA - if (!via_modem && disp_bi ) { - prom_drawstring("xmon uses screen and keyboard\n"); + if (np != NULL && disp_bi && find_via_cuda()) use_screen = 1; - } -#endif #endif + if (use_screen) + prom_drawstring("xmon uses screen and keyboard\n"); +#endif /* CONFIG_BOOTX_TEXT */ #ifdef CHRP_ESCC addr = 0xc1013020; @@ -140,12 +148,22 @@ char *p = ptr; int i, c, ct; +#ifdef CONFIG_SMP + static unsigned long xmon_write_lock; + int lock_wait = 1000000; + int locked; + + while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0) + if (--lock_wait == 0) + break; +#endif + #ifdef CONFIG_BOOTX_TEXT if (use_screen) { /* write it on the screen */ for (i = 0; i < nb; ++i) prom_drawchar(*p++); - return nb; + goto out; } #endif if (!scc_initialized) @@ -166,8 +184,15 @@ } buf_access(); *sccd = c; + eieio(); } - return i; + + out: +#ifdef CONFIG_SMP + if (!locked) + clear_bit(0, &xmon_write_lock); +#endif + return nb; } int xmon_wants_key; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/ppc/xmon/xmon.c linux.ac/arch/ppc/xmon/xmon.c --- linux-2.4.0/arch/ppc/xmon/xmon.c Sun Sep 17 17:48:07 2000 +++ linux.ac/arch/ppc/xmon/xmon.c Mon Dec 18 20:45:53 2000 @@ -406,6 +406,7 @@ break; case 'M': print_sysmap(); + break; case 'S': super_regs(); break; @@ -795,6 +796,8 @@ extern char *sysmap; if ( sysmap ) printf("System.map: \n%s", sysmap); + else + printf("No System.map\n"); } void diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/Makefile linux.ac/arch/s390/Makefile --- linux-2.4.0/arch/s390/Makefile Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/Makefile Fri Jan 5 00:00:32 2001 @@ -14,6 +14,7 @@ # LD=$(CROSS_COMPILE)ld -m elf_s390 +CPP=$(CC) -E OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S LDFLAGS=-e start LINKFLAGS =-T $(TOPDIR)/arch/s390/vmlinux.lds $(LDFLAGS) @@ -21,6 +22,11 @@ CFLAGS_PIPE := -pipe CFLAGS_NSR := -fno-strength-reduce CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR) + + +ifdef SMP +CFLAGS := $(CFLAGS) -D__SMP__ +endif HEAD := arch/s390/kernel/head.o arch/s390/kernel/init_task.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/boot/Makefile linux.ac/arch/s390/boot/Makefile --- linux-2.4.0/arch/s390/boot/Makefile Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/boot/Makefile Fri Jan 5 00:00:32 2001 @@ -10,12 +10,11 @@ OBJCOPY = $(CROSS_COMPILE)objcopy O_TARGET := -O_OBJS := include $(TOPDIR)/Rules.make .S.o: - $(CC) $(AFLAGS) -traditional -c $< -o $*.o + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o %.lnk: %.o $(LD) -Ttext 0x0 -o $@ $< diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/boot/ipldump.S linux.ac/arch/s390/boot/ipldump.S --- linux-2.4.0/arch/s390/boot/ipldump.S Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/boot/ipldump.S Fri Jan 5 00:00:32 2001 @@ -9,6 +9,7 @@ * write a dump of the real storage after the ipl record on that tape. */ +#include #include #include @@ -38,7 +39,7 @@ # # find out memory size # - mvc 104(8,0),.Lpcmem0 # setup program check handler + mvc 104(8),.Lpcmem0 # setup program check handler slr %r3,%r3 lhi %r2,1 sll %r2,20 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/boot/ipleckd.S linux.ac/arch/s390/boot/ipleckd.S --- linux-2.4.0/arch/s390/boot/ipleckd.S Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/boot/ipleckd.S Fri Jan 5 00:00:32 2001 @@ -3,7 +3,7 @@ # IPL record for 3380/3390 DASD # # S390 version -# Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation +# Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation # Author(s): Holger Smolinski # # @@ -11,6 +11,8 @@ # FIXME: should insert zeroes into memory when filling holes # FIXME: calculate blkpertrack from rdc data and blksize +# change 09/20/00 removed obsolete store of ipldevice to textesegment + # Usage of registers # r1: ipl subchannel ( general use, dont overload without save/restore !) # r10: @@ -39,7 +41,7 @@ .org 0xf0 # Lets start now... _start: .globl _start - l %r1,__LC_SUBCHANNEL_ID # get IPL-subchannel from lowcore + l %r1,__LC_SUBCHANNEL_ID # get IPL-subchannel from lowcore st %r1,__LC_IPLDEV # keep it for reipl stsch .Lrdcdata oi .Lrdcdata+5,0x84 # enable ssch and multipath mode @@ -111,10 +113,10 @@ mvc 0x600(256,%r3),0x180(%r4) mvc 0x700(256,%r3),0x280(%r4) .Lrunkern: - lhi %r2,17 - sll %r2,12 - st %r1,0xc6c(%r2) # store iplsubchannel to lowcore - st %r1,0xc6c # store iplsubchannel to lowcore +# lhi %r2,17 +# sll %r2,12 +# st %r1,0xc6c(%r2) # store iplsubchannel to lowcore +# st %r1,0xc6c # store iplsubchannel to lowcore br %r3 # This function does the start IO # r2: number of first block to read ( input by caller ) @@ -140,17 +142,16 @@ lr %r15,%r4 # save number or blocks slr %r7,%r7 icm %r7,3,.Lrdcdata+14 # load heads to r7 + lhi %r6,9 + clc .Lrdcdata+3(2),.L9345 + je .L011 + lhi %r6,10 + clc .Lrdcdata+3(2),.L3380 + je .L011 + lhi %r6,12 clc .Lrdcdata+3(2),.L3390 - jne .L010 # 3380 or 3390 ? - lhi %r6,12 # setup r6 correct! - j .L011 -.L010: - clc .Lrdcdata+3(2),.L9343 - jne .L013 - lhi %r6,9 - j .L011 -.L013: - lhi %r6,10 + je .L011 + bras %r14,.Ldisab .L011: # loop for nbl times .Lrdloop: @@ -245,10 +246,13 @@ .long 0x00008000 # they are loaded with a LM .L3390: .word 0x3390 -.L9343: - .word 0x9343 +.L9345: + .word 0x9345 +.L3380: + .word 0x3380 .Lnull: .long 0x00000000,0x00000000 + .align 4 .Lrdcdata: .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/config.in linux.ac/arch/s390/config.in --- linux-2.4.0/arch/s390/config.in Thu Nov 16 20:51:28 2000 +++ linux.ac/arch/s390/config.in Fri Jan 5 00:00:32 2001 @@ -44,30 +44,19 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL +define CONFIG_KCORE ELF tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF - +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG endmenu source drivers/s390/Config.in -mainmenu_option next_comment -comment 'Character devices' -bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS -if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then - int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 -fi - -endmenu - if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi source fs/Config.in - -# source drivers/char/Config.in - -# source drivers/media/Config.in mainmenu_option next_comment comment 'Kernel hacking' diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/defconfig linux.ac/arch/s390/defconfig --- linux-2.4.0/arch/s390/defconfig Mon Jun 19 21:25:06 2000 +++ linux.ac/arch/s390/defconfig Fri Jan 5 00:00:32 2001 @@ -1,6 +1,9 @@ # # Automatically generated by make menuconfig: don't edit # +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_MCA is not set CONFIG_UID16=y CONFIG_ARCH_S390=y @@ -20,7 +23,7 @@ # CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y # # General setup @@ -34,41 +37,60 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PROCESS_DEBUG is not set # -# S/390 block device drivers +# Block device drivers # CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=24576 CONFIG_BLK_DEV_INITRD=y -# CONFIG_MDISK is not set +CONFIG_BLK_DEV_XPRAM=m CONFIG_DASD=y CONFIG_DASD_ECKD=y -# CONFIG_DASD_MDSK is not set +CONFIG_DASD_FBA=y # -# S/390 Network device support +# Multi-device support (RAID and LVM) # -# CONFIG_CHANDEV is not set -CONFIG_NETDEVICES=y -CONFIG_CTC=y -CONFIG_IUCV=y -# CONFIG_DUMMY is not set -CONFIG_NET_ETHERNET=y -CONFIG_TR=y -# CONFIG_FDDI is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +# CONFIG_MD_LINEAR is not set +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m +CONFIG_BLK_DEV_LVM=m +CONFIG_LVM_PROC_FS=y # -# S/390 Terminal and Console options +# Character device drivers # +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 CONFIG_3215=y CONFIG_3215_CONSOLE=y CONFIG_HWC=y CONFIG_HWC_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_S390_TAPE=m +CONFIG_S390_TAPE_CHAR=y +CONFIG_S390_TAPE_BLOCK=y +CONFIG_S390_TAPE_3490=y +CONFIG_S390_TAPE_3480=y + +# +# Network device drivers +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +CONFIG_NET_ETHERNET=y +CONFIG_TR=y +# CONFIG_FDDI is not set +# CONFIG_CHANDEV is not set +CONFIG_CTC=m +CONFIG_IUCV=m # # Networking options @@ -82,25 +104,24 @@ # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set -CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set @@ -118,6 +139,7 @@ # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -126,28 +148,37 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set @@ -155,6 +186,16 @@ CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -168,10 +209,10 @@ # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set # CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # # Kernel hacking # -# CONFIG_REMOTE_DEBUG is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/Makefile linux.ac/arch/s390/kernel/Makefile --- linux-2.4.0/arch/s390/kernel/Makefile Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/kernel/Makefile Fri Jan 5 00:00:32 2001 @@ -8,47 +8,25 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.o: - $(CC) $(AFLAGS) -traditional -c $< -o $*.o + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o all: kernel.o head.o init_task.o O_TARGET := kernel.o -O_OBJS := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \ - setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390fpu.o s390io.o s390mach.o s390dyn.o reipl.o -OX_OBJS := s390_ksyms.o -MX_OBJS := - -ifdef CONFIG_SMP -O_OBJS += smp.o -endif - -ifdef CONFIG_PCI -O_OBJS += bios32.o -endif -ifdef CONFIG_MCA -O_OBJS += mca.o -endif - -ifeq ($(CONFIG_MTRR),y) -OX_OBJS += mtrr.o -else - ifeq ($(CONFIG_MTRR),m) - MX_OBJS += mtrr.o - endif -endif +export-objs := s390_ksyms.o +obj-y := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \ + setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ + semaphore.o s390fpu.o reipl.o s390_ext.o debug.o -ifeq ($(CONFIG_IEEEFPU_EMULATION),y) - O_OBJS += mathemu.o floatlib.o -endif +obj-$(CONFIG_MODULES) += s390_ksyms.o +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_IEEEFPU_EMULATION) += mathemu.o floatlib.o # # Kernel debugging # -ifdef CONFIG_REMOTE_DEBUG -O_OBJS += gdb-stub.o #gdb-low.o -endif +obj-$(CONFIG_REMOTE_DEBUG) += gdb-stub.o #gdb-low.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/cpcmd.c linux.ac/arch/s390/kernel/cpcmd.c --- linux-2.4.0/arch/s390/kernel/cpcmd.c Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/kernel/cpcmd.c Fri Jan 5 00:00:32 2001 @@ -8,7 +8,7 @@ #include #include -#include +#include #include void cpcmd(char *cmd, char *response, int rlen) @@ -22,10 +22,10 @@ ASCEBC(obuffer,olen); if (response != NULL && rlen > 0) { - asm volatile ("LRA 2,0(0,%0)\n\t" + asm volatile ("LRA 2,0(%0)\n\t" "LR 4,%1\n\t" "O 4,%4\n\t" - "LRA 3,0(0,%2)\n\t" + "LRA 3,0(%2)\n\t" "LR 5,%3\n\t" ".long 0x83240008 # Diagnose 83\n\t" : /* no output */ @@ -34,7 +34,7 @@ : "2", "3", "4", "5" ); EBCASC(response, rlen); } else { - asm volatile ("LRA 2,0(0,%0)\n\t" + asm volatile ("LRA 2,0(%0)\n\t" "LR 3,%1\n\t" ".long 0x83230008 # Diagnose 83\n\t" : /* no output */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/debug.c linux.ac/arch/s390/kernel/debug.c --- linux-2.4.0/arch/s390/kernel/debug.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/s390/kernel/debug.c Fri Jan 5 00:00:32 2001 @@ -0,0 +1,1166 @@ +/* + * arch/s390/kernel/debug.c + * S/390 debug facility + * + * Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, + * IBM Corporation + * Author(s): Michael Holzheu (holzheu@de.ibm.com), + * Holger Smolinski (Holger.Smolinski@de.ibm.com) + * + * Bugreports to: + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef MODULE +#include +#endif + +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#if defined(CONFIG_ARCH_S390X) +#define DEBUG_PROC_HEADER_SIZE 46 +#else +#define DEBUG_PROC_HEADER_SIZE 38 +#endif + +#define ADD_BUFFER 1000 + +/* typedefs */ + +typedef struct file_private_info { + loff_t len; /* length of output in byte */ + int size; /* size of buffer for output */ + char *data; /* buffer for output */ + debug_info_t *debug_info; /* the debug information struct */ + struct debug_view *view; /* used view of debug info */ +} file_private_info_t; + +extern void tod_to_timeval(uint64_t todval, struct timeval *xtime); + +/* internal function prototyes */ + +static int debug_init(void); +static int debug_format_output(debug_info_t * debug_area, char *buf, + int size, struct debug_view *view); +static ssize_t debug_output(struct file *file, char *user_buf, + size_t user_len, loff_t * offset); +static ssize_t debug_input(struct file *file, const char *user_buf, + size_t user_len, loff_t * offset); +static int debug_open(struct inode *inode, struct file *file); +static int debug_close(struct inode *inode, struct file *file); +static struct proc_dir_entry +*debug_create_proc_dir_entry(struct proc_dir_entry *root, + const char *name, mode_t mode, + struct inode_operations *iops, + struct file_operations *fops); +static void debug_delete_proc_dir_entry(struct proc_dir_entry *root, + struct proc_dir_entry *entry); +static debug_info_t* debug_info_create(char *name, int page_order, int nr_areas, int buf_size); +static void debug_info_get(debug_info_t *); +static void debug_info_put(debug_info_t *); +static int debug_prolog_level_fn(debug_info_t * id, + struct debug_view *view, char *out_buf); +static int debug_input_level_fn(debug_info_t * id, struct debug_view *view, + struct file *file, const char *user_buf, + size_t user_buf_size, loff_t * offset); +static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view, + char *out_buf, const char *in_buf); +static int debug_raw_format_fn(debug_info_t * id, + struct debug_view *view, char *out_buf, + const char *in_buf); +static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view, + int area, debug_entry_t * entry, char *out_buf); + +/* globals */ + +struct debug_view debug_raw_view = { + "raw", + NULL, + &debug_raw_header_fn, + &debug_raw_format_fn, + NULL +}; + +struct debug_view debug_hex_ascii_view = { + "hex_ascii", + NULL, + &debug_dflt_header_fn, + &debug_hex_ascii_format_fn, + NULL +}; + +struct debug_view debug_level_view = { + "level", + &debug_prolog_level_fn, + NULL, + NULL, + &debug_input_level_fn +}; + +/* static globals */ + +static debug_info_t *debug_area_first = NULL; +static debug_info_t *debug_area_last = NULL; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) +static struct semaphore debug_lock = MUTEX; +#else +DECLARE_MUTEX(debug_lock); +#endif + +static int initialized = 0; + +static struct file_operations debug_file_ops = { + read: debug_output, + write: debug_input, + open: debug_open, + release: debug_close, +}; + +static struct inode_operations debug_inode_ops = { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) + default_file_ops: &debug_file_ops, /* file ops */ +#endif +}; + + +static struct proc_dir_entry *debug_proc_root_entry; + + +/* functions */ + +/* + * debug_info_create + * - create new debug-info + */ + +static debug_info_t* debug_info_create(char *name, int page_order, + int nr_areas, int buf_size) +{ + debug_info_t* rc; + int i; + + /* alloc everything */ + + rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC); + if(!rc) + goto fail_malloc_rc; + rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC); + if(!rc->active_entry) + goto fail_malloc_active_entry; + memset(rc->active_entry, 0, nr_areas * sizeof(int)); + rc->areas = (debug_entry_t **) kmalloc(nr_areas * + sizeof(debug_entry_t *), + GFP_ATOMIC); + if (!rc->areas) + goto fail_malloc_areas; + for (i = 0; i < nr_areas; i++) { + rc->areas[i] = + (debug_entry_t *) __get_free_pages(GFP_ATOMIC, + page_order); + if (!rc->areas[i]) { + for (i--; i >= 0; i--) { + free_pages((unsigned long) rc->areas[i], + page_order); + } + goto fail_malloc_areas2; + } else { + memset(rc->areas[i], 0, PAGE_SIZE << page_order); + } + } + + /* initialize members */ + + spin_lock_init(&rc->lock); + rc->page_order = page_order; + rc->nr_areas = nr_areas; + rc->active_area = 0; + rc->level = DEBUG_DEFAULT_LEVEL; + rc->buf_size = buf_size; + rc->entry_size = sizeof(debug_entry_t) + buf_size; + strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))); + rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0; + memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *)); + memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS * + sizeof(struct proc_dir_entry*)); + atomic_set(&(rc->ref_count), 0); + rc->proc_root_entry = + debug_create_proc_dir_entry(debug_proc_root_entry, rc->name, + S_IFDIR | S_IRUGO | S_IXUGO | + S_IWUSR | S_IWGRP, NULL, NULL); + + /* append new element to linked list */ + + if(debug_area_first == NULL){ + /* first element in list */ + debug_area_first = rc; + rc->prev = NULL; + } + else{ + /* append element to end of list */ + debug_area_last->next = rc; + rc->prev = debug_area_last; + } + debug_area_last = rc; + rc->next = NULL; + + debug_info_get(rc); + return rc; + +fail_malloc_areas2: + kfree(rc->areas); +fail_malloc_areas: + kfree(rc->active_entry); +fail_malloc_active_entry: + kfree(rc); +fail_malloc_rc: + return NULL; +} + +/* + * debug_info_get + * - increments reference count for debug-info + */ + +static void debug_info_get(debug_info_t * db_info) +{ + if (db_info) + atomic_inc(&db_info->ref_count); +} + +/* + * debug_info_put: + * - decreases reference count for debug-info and frees it if necessary + */ + +static void debug_info_put(debug_info_t *db_info) +{ + int i; + + if (!db_info) + return; + if (atomic_dec_and_test(&db_info->ref_count)) { + printk(KERN_INFO "debug: freeing debug area %p (%s)\n", + db_info, db_info->name); + for (i = 0; i < DEBUG_MAX_VIEWS; i++) { + if (db_info->views[i] != NULL) + debug_delete_proc_dir_entry + (db_info->proc_root_entry, + db_info->proc_entries[i]); + } + debug_delete_proc_dir_entry(debug_proc_root_entry, + db_info->proc_root_entry); + for (i = 0; i < db_info->nr_areas; i++) { + free_pages((unsigned long) db_info->areas[i], + db_info->page_order); + } + kfree(db_info->areas); + kfree(db_info->active_entry); + if(db_info == debug_area_first) + debug_area_first = db_info->next; + if(db_info == debug_area_last) + debug_area_last = db_info->prev; + if(db_info->prev) db_info->prev->next = db_info->next; + if(db_info->next) db_info->next->prev = db_info->prev; + kfree(db_info); + } +} + + +/* + * debug_output: + * - called for user read() + * - copies formated output form private_data of the file + * handle to the user buffer + */ + +static ssize_t debug_output(struct file *file, /* file descriptor */ + char *user_buf, /* user buffer */ + size_t user_len, /* length of buffer */ + loff_t *offset /* offset in the file */ ) +{ + loff_t len; + int rc; + file_private_info_t *p_info; + + p_info = ((file_private_info_t *) file->private_data); + if (*offset >= p_info->len) { + return 0; /* EOF */ + } else { + len = MIN(user_len, (p_info->len - *offset)); + if ((rc = copy_to_user(user_buf, &(p_info->data[*offset]),len))) + return rc;; + (*offset) += len; + return len; /* number of bytes "read" */ + } +} + +/* + * debug_input: + * - called for user write() + * - calls input function of view + */ + +static ssize_t debug_input(struct file *file, + const char *user_buf, size_t length, + loff_t *offset) +{ + int rc = 0; + file_private_info_t *p_info; + + down(&debug_lock); + p_info = ((file_private_info_t *) file->private_data); + if (p_info->view->input_proc) + rc = p_info->view->input_proc(p_info->debug_info, + p_info->view, file, user_buf, + length, offset); + up(&debug_lock); + return rc; /* number of input characters */ +} + +/* + * debug_format_output: + * - calls prolog, header and format functions of view to format output + */ + +static int debug_format_output(debug_info_t * debug_area, char *buf, + int size, struct debug_view *view) +{ + int len = 0; + int i, j; + int nr_of_entries; + debug_entry_t *act_entry; + + /* print prolog */ + if (view->prolog_proc) + len += view->prolog_proc(debug_area, view, buf); + /* print debug records */ + if (!(view->format_proc) && !(view->header_proc)) + goto out; + nr_of_entries = PAGE_SIZE / debug_area->entry_size + << debug_area->page_order; + for (i = 0; i < debug_area->nr_areas; i++) { + act_entry = debug_area->areas[i]; + for (j = 0; j < nr_of_entries; j++) { + if (act_entry->id.fields.used == 0) + break; /* empty entry */ + if (view->header_proc) + len += view->header_proc(debug_area, view, i, + act_entry, buf + len); + if (view->format_proc) + len += view->format_proc(debug_area, view, + buf + len, + DEBUG_DATA(act_entry)); + if (len > size) { + printk(KERN_ERR + "debug: error -- memory exceeded for (%s/%s)\n", + debug_area->name, view->name); + printk(KERN_ERR "debug: fix view %s!!\n", + view->name); + printk(KERN_ERR + "debug: area: %i (0 - %i) entry: %i (0 - %i)\n", + i, debug_area->nr_areas - 1, j, + nr_of_entries - 1); + goto out; + } + act_entry = (debug_entry_t *) (((char *) act_entry) + + debug_area->entry_size); + } + } + out: + return len; +} + + +/* + * debug_open: + * - called for user open() + * - copies formated output to private_data area of the file + * handle + */ + +static int debug_open(struct inode *inode, struct file *file) +{ + int i = 0, size = 0, rc = 0, f_entry_size = 0; + file_private_info_t *p_info; + debug_info_t* debug_info; + +#ifdef DEBUG + printk("debug_open\n"); +#endif + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + down(&debug_lock); + + /* find debug log and view */ + + debug_info = debug_area_first; + while(debug_info != NULL){ + for (i = 0; i < DEBUG_MAX_VIEWS; i++) { + if (debug_info->views[i] == NULL) + continue; + else if (debug_info->proc_entries[i]->low_ino == + file->f_dentry->d_inode->i_ino) { + goto found; /* found view ! */ + } + } + debug_info = debug_info->next; + } + /* no entry found */ + rc = -EINVAL; + goto out; + found: + if ((file->private_data = + kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) { + printk(KERN_ERR "debug_open: kmalloc failed\n"); + rc = -ENOMEM; + goto out; + } + p_info = (file_private_info_t *) file->private_data; + + /* + * the size for the formated output is calculated + * with the following formula: + * + * prolog-size + * + + * (record header size + record data field size) + * * number of entries per page + * * number of pages per area + * * number of areas + */ + + if (debug_info->views[i]->prolog_proc) + size += + debug_info->views[i]->prolog_proc(debug_info, + debug_info-> + views[i], NULL); + + if (debug_info->views[i]->header_proc) + f_entry_size = + debug_info->views[i]->header_proc(debug_info, + debug_info-> + views[i], 0, NULL, + NULL); + if (debug_info->views[i]->format_proc) + f_entry_size += + debug_info->views[i]->format_proc(debug_info, + debug_info-> + views[i], NULL, + NULL); + + size += f_entry_size + * (PAGE_SIZE / debug_info->entry_size + << debug_info->page_order) + * debug_info->nr_areas + 1; /* terminating \0 */ +#ifdef DEBUG + printk("debug_open: size: %i\n", size); +#endif + + /* alloc some bytes more to be safe against bad views */ + if ((p_info->data = vmalloc(size + ADD_BUFFER)) == 0) { + printk(KERN_ERR "debug_open: vmalloc failed\n"); + vfree(file->private_data); + rc = -ENOMEM; + goto out; + } + + p_info->size = size; + p_info->debug_info = debug_info; + p_info->view = debug_info->views[i]; + + spin_lock_irq(&debug_info->lock); + + p_info->len = + debug_format_output(debug_info, p_info->data, size, + debug_info->views[i]); +#ifdef DEBUG + { + int ilen = p_info->len; + printk("debug_open: len: %i\n", ilen); + } +#endif + + spin_unlock_irq(&debug_info->lock); + debug_info_get(debug_info); + + out: + up(&debug_lock); +#ifdef MODULE + if (rc != 0) + MOD_DEC_USE_COUNT; +#endif + return rc; +} + +/* + * debug_close: + * - called for user close() + * - deletes private_data area of the file handle + */ + +static int debug_close(struct inode *inode, struct file *file) +{ + file_private_info_t *p_info; +#ifdef DEBUG + printk("debug_close\n"); +#endif + down(&debug_lock); + p_info = (file_private_info_t *) file->private_data; + debug_info_put(p_info->debug_info); + if (p_info->data) { + vfree(p_info->data); + kfree(file->private_data); + } + up(&debug_lock); + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + return 0; /* success */ +} + +/* + * debug_create_proc_dir_entry: + * - initializes proc-dir-entry and registers it + */ + +static struct proc_dir_entry *debug_create_proc_dir_entry + (struct proc_dir_entry *root, const char *name, mode_t mode, + struct inode_operations *iops, struct file_operations *fops) +{ + struct proc_dir_entry *rc = NULL; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) + const char *fn = name; + int len; + len = strlen(fn); + + rc = (struct proc_dir_entry *) kmalloc(sizeof(struct proc_dir_entry) + + len + 1, GFP_ATOMIC); + if (!rc) + goto out; + + memset(rc, 0, sizeof(struct proc_dir_entry)); + memcpy(((char *) rc) + sizeof(*rc), fn, len + 1); + rc->name = ((char *) rc) + sizeof(*rc); + rc->namelen = len; + rc->low_ino = 0, rc->mode = mode; + rc->nlink = 1; + rc->uid = 0; + rc->gid = 0; + rc->size = 0; + rc->get_info = NULL; + rc->ops = iops; + + proc_register(root, rc); +#else + rc = create_proc_entry(name, mode, root); + if (!rc) + goto out; + if (fops) + rc->proc_fops = fops; +#endif + + out: + return rc; +} + + +/* + * delete_proc_dir_entry: + */ + +static void debug_delete_proc_dir_entry + (struct proc_dir_entry *root, struct proc_dir_entry *proc_entry) +{ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) + proc_unregister(root, proc_entry->low_ino); + kfree(proc_entry); +#else + remove_proc_entry(proc_entry->name, root); +#endif +} + +/* + * debug_register: + * - creates and initializes debug area for the caller + * - returns handle for debug area + */ + +debug_info_t *debug_register + (char *name, int page_order, int nr_areas, int buf_size) +{ + debug_info_t *rc = NULL; + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + if (!initialized) + debug_init(); + down(&debug_lock); + + /* create new debug_info */ + + rc = debug_info_create(name, page_order, nr_areas, buf_size); + if(!rc) + goto out; + debug_register_view(rc, &debug_level_view); + printk(KERN_INFO + "debug: reserved %d areas of %d pages for debugging %s\n", + nr_areas, 1 << page_order, rc->name); + out: + if (rc == NULL){ + printk(KERN_ERR "debug: debug_register failed for %s\n",name); +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + } + up(&debug_lock); + return rc; +} + +/* + * debug_unregister: + * - give back debug area + */ + +void debug_unregister(debug_info_t * id) +{ + if (!id) + goto out; + down(&debug_lock); + printk(KERN_INFO "debug: unregistering %s\n", id->name); + debug_info_put(id); + up(&debug_lock); + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + out: + return; +} + +/* + * debug_set_level: + * - set actual debug level + */ + +void debug_set_level(debug_info_t* id, int new_level) +{ + long flags; + if(!id) + return; + spin_lock_irqsave(&id->lock,flags); + if(new_level == DEBUG_OFF_LEVEL){ + id->level = DEBUG_OFF_LEVEL; + printk(KERN_INFO "debug: %s: switched off\n",id->name); + } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) { + printk(KERN_INFO + "debug: %s: level %i is out of range (%i - %i)\n", + id->name, new_level, 0, DEBUG_MAX_LEVEL); + } else { + id->level = new_level; + printk(KERN_INFO + "debug: %s: new level %i\n",id->name,id->level); + } + spin_unlock_irqrestore(&id->lock,flags); +} + + +/* + * proceed_active_entry: + * - set active entry to next in the ring buffer + */ + +static inline void proceed_active_entry(debug_info_t * id) +{ + if ((id->active_entry[id->active_area] += id->entry_size) + > ((PAGE_SIZE << (id->page_order)) - id->entry_size)) + id->active_entry[id->active_area] = 0; +} + +/* + * proceed_active_area: + * - set active area to next in the ring buffer + */ + +static inline void proceed_active_area(debug_info_t * id) +{ + id->active_area++; + id->active_area = id->active_area % id->nr_areas; +} + +/* + * get_active_entry: + */ + +static inline debug_entry_t *get_active_entry(debug_info_t * id) +{ + return (debug_entry_t *) ((char *) id->areas[id->active_area] + + id->active_entry[id->active_area]); +} + +/* + * debug_common: + * - set timestamp, caller address, cpu number etc. + */ + +static inline debug_entry_t *debug_common(debug_info_t * id) +{ + debug_entry_t *active; + + active = get_active_entry(id); + STCK(active->id.stck); + active->id.fields.cpuid = smp_processor_id(); + active->id.fields.used = 1; + active->caller = __builtin_return_address(0); + return active; +} + +/* + * debug_event: + */ + +debug_entry_t *debug_event(debug_info_t * id, int level, void *buf, + int len) +{ + long flags; + debug_entry_t *active = NULL; + + if ((!id) || (level > id->level)) + goto out; + spin_lock_irqsave(&id->lock, flags); + active = debug_common(id); + active->id.fields.exception = 0; + memset(DEBUG_DATA(active), 0, id->buf_size); + memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size)); + proceed_active_entry(id); + spin_unlock_irqrestore(&id->lock, flags); + out: + return active; +} + +/* + * debug_int_event: + */ + +debug_entry_t *debug_int_event(debug_info_t * id, int level, + unsigned int tag) +{ + long flags; + debug_entry_t *active = NULL; + + if ((!id) || (level > id->level)) + goto out; + spin_lock_irqsave(&id->lock, flags); + active = debug_common(id); + active->id.fields.exception = 0; + memset(DEBUG_DATA(active), 0, id->buf_size); + memcpy(DEBUG_DATA(active), &tag, MIN(sizeof(unsigned int), id->buf_size)); + proceed_active_entry(id); + spin_unlock_irqrestore(&id->lock, flags); + out: + return active; +} + +/* + * debug_text_event: + */ + +debug_entry_t *debug_text_event(debug_info_t * id, int level, + const char *txt) +{ + long flags; + debug_entry_t *active = NULL; + + if ((!id) || (level > id->level)) + goto out; + spin_lock_irqsave(&id->lock, flags); + active = debug_common(id); + memset(DEBUG_DATA(active), 0, id->buf_size); + strncpy(DEBUG_DATA(active), txt, MIN(strlen(txt), id->buf_size)); + active->id.fields.exception = 0; + proceed_active_entry(id); + spin_unlock_irqrestore(&id->lock, flags); + out: + return active; + +} + +/* + * debug_exception: + */ + +debug_entry_t *debug_exception(debug_info_t * id, int level, void *buf, + int len) +{ + long flags; + debug_entry_t *active = NULL; + + if ((!id) || (level > id->level)) + goto out; + spin_lock_irqsave(&id->lock, flags); + active = debug_common(id); + active->id.fields.exception = 1; + memset(DEBUG_DATA(active), 0, id->buf_size); + memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size)); + proceed_active_entry(id); + proceed_active_area(id); + spin_unlock_irqrestore(&id->lock, flags); + out: + return active; +} + +/* + * debug_int_exception: + */ + +debug_entry_t *debug_int_exception(debug_info_t * id, int level, + unsigned int tag) +{ + long flags; + debug_entry_t *active = NULL; + + if ((!id) || (level > id->level)) + goto out; + spin_lock_irqsave(&id->lock, flags); + active = debug_common(id); + active->id.fields.exception = 1; + memset(DEBUG_DATA(active), 0, id->buf_size); + memcpy(DEBUG_DATA(active), &tag, + MIN(sizeof(unsigned int), id->buf_size)); + proceed_active_entry(id); + proceed_active_area(id); + spin_unlock_irqrestore(&id->lock, flags); + out: + return active; +} + +/* + * debug_text_exception: + */ + +debug_entry_t *debug_text_exception(debug_info_t * id, int level, + const char *txt) +{ + long flags; + debug_entry_t *active = NULL; + + if ((!id) || (level > id->level)) + goto out; + spin_lock_irqsave(&id->lock, flags); + active = debug_common(id); + memset(DEBUG_DATA(active), 0, id->buf_size); + strncpy(DEBUG_DATA(active), txt, MIN(strlen(txt), id->buf_size)); + active->id.fields.exception = 1; + proceed_active_entry(id); + proceed_active_area(id); + spin_unlock_irqrestore(&id->lock, flags); + out: + return active; + +} + +/* + * debug_init: + * - is called exactly once to initialize the debug feature + */ + +int debug_init(void) +{ + int rc = 0; + + down(&debug_lock); + if (!initialized) { + debug_proc_root_entry = + debug_create_proc_dir_entry(&proc_root, DEBUG_DIR_ROOT, + S_IFDIR | S_IRUGO | S_IXUGO + | S_IWUSR | S_IWGRP, NULL, + NULL); + printk(KERN_INFO "debug: Initialization complete\n"); + initialized = 1; + } + up(&debug_lock); + + return rc; +} + +/* + * debug_register_view: + */ + +int debug_register_view(debug_info_t * id, struct debug_view *view) +{ + int rc = 0; + int i; + long flags; + mode_t mode = S_IFREG; + + if (!id) + goto out; + spin_lock_irqsave(&id->lock, flags); + for (i = 0; i < DEBUG_MAX_VIEWS; i++) { + if (id->views[i] == NULL) + break; + } + if (i == DEBUG_MAX_VIEWS) { + printk(KERN_WARNING "debug: cannot register view %s/%s\n", + id->name,view->name); + printk(KERN_WARNING + "debug: maximum number of views reached (%i)!\n", i); + rc = -1; + } + else { + id->views[i] = view; + if (view->prolog_proc || view->format_proc || view->header_proc) + mode |= S_IRUSR; + if (view->input_proc) + mode |= S_IWUSR; + id->proc_entries[i] = + debug_create_proc_dir_entry(id->proc_root_entry, + view->name, mode, + &debug_inode_ops, + &debug_file_ops); + rc = 0; + } + spin_unlock_irqrestore(&id->lock, flags); + out: + return rc; +} + +/* + * debug_unregister_view: + */ + +int debug_unregister_view(debug_info_t * id, struct debug_view *view) +{ + int rc = 0; + int i; + long flags; + + if (!id) + goto out; + spin_lock_irqsave(&id->lock, flags); + for (i = 0; i < DEBUG_MAX_VIEWS; i++) { + if (id->views[i] == view) + break; + } + if (i == DEBUG_MAX_VIEWS) + rc = -1; + else { + debug_delete_proc_dir_entry(id->proc_root_entry, + id->proc_entries[i]); + id->views[i] = NULL; + rc = 0; + } + spin_unlock_irqrestore(&id->lock, flags); + out: + return rc; +} + +/* + * functions for debug-views + *********************************** +*/ + +/* + * prints out actual debug level + */ + +static int debug_prolog_level_fn(debug_info_t * id, + struct debug_view *view, char *out_buf) +{ + int rc = 0; + + if (out_buf == NULL) { + rc = 2; + goto out; + } + if(id->level == -1) rc = sprintf(out_buf,"-\n"); + else rc = sprintf(out_buf, "%i\n", id->level); + out: + return rc; +} + +/* + * reads new debug level + */ + +static int debug_input_level_fn(debug_info_t * id, struct debug_view *view, + struct file *file, const char *user_buf, + size_t in_buf_size, loff_t * offset) +{ + char input_buf[1]; + int rc = in_buf_size; + + if (*offset != 0) + goto out; + if ((rc = copy_from_user(input_buf, user_buf, 1))) + goto out; + if (isdigit(input_buf[0])) { + int new_level = ((int) input_buf[0] - (int) '0'); + debug_set_level(id, new_level); + } else if(input_buf[0] == '-') { + debug_set_level(id, DEBUG_OFF_LEVEL); + } else { + printk(KERN_INFO "debug: level `%c` is not valid\n", + input_buf[0]); + } + out: + *offset += in_buf_size; + return rc; /* number of input characters */ +} + +/* + * prints debug header in raw format + */ + +int debug_raw_header_fn(debug_info_t * id, struct debug_view *view, + int area, debug_entry_t * entry, char *out_buf) +{ + int rc; + + rc = sizeof(debug_entry_t); + if (out_buf == NULL) + goto out; + memcpy(out_buf,entry,sizeof(debug_entry_t)); + out: + return rc; +} + +/* + * prints debug data in raw format + */ + +static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view, + char *out_buf, const char *in_buf) +{ + int rc; + + rc = id->buf_size; + if (out_buf == NULL || in_buf == NULL) + goto out; + memcpy(out_buf, in_buf, id->buf_size); + out: + return rc; +} + +/* + * prints debug data in hex/ascii format + */ + +static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view, + char *out_buf, const char *in_buf) +{ + int i, rc = 0; + + if (out_buf == NULL || in_buf == NULL) { + rc = id->buf_size * 4 + 3; + goto out; + } + for (i = 0; i < id->buf_size; i++) { + rc += sprintf(out_buf + rc, "%02x ", + ((unsigned char *) in_buf)[i]); + } + rc += sprintf(out_buf + rc, "| "); + for (i = 0; i < id->buf_size; i++) { + unsigned char c = in_buf[i]; + if (!isprint(c)) + rc += sprintf(out_buf + rc, "."); + else + rc += sprintf(out_buf + rc, "%c", c); + } + rc += sprintf(out_buf + rc, "\n"); + out: + return rc; +} + +/* + * prints header for debug entry + */ + +int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, + int area, debug_entry_t * entry, char *out_buf) +{ + struct timeval time_val; + unsigned long long time; + char *except_str; + unsigned long caller; + int rc = 0; + + if (out_buf == NULL) { + rc = DEBUG_PROC_HEADER_SIZE; + goto out; + } + + time = entry->id.stck; + /* adjust todclock to 1970 */ + time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); + tod_to_timeval(time, &time_val); + + if (entry->id.fields.exception) + except_str = "*"; + else + except_str = "-"; + caller = (unsigned long) entry->caller; +#if defined(CONFIG_ARCH_S390X) + rc += sprintf(out_buf, "%02i %011lu:%06lu %1s %02i %016lx ", + area, time_val.tv_sec, + time_val.tv_usec, except_str, + entry->id.fields.cpuid, caller); +#else + caller &= 0x7fffffff; + rc += sprintf(out_buf, "%02i %011lu:%06lu %1s %02i %08lx ", + area, time_val.tv_sec, + time_val.tv_usec, except_str, + entry->id.fields.cpuid, caller); +#endif + out: + return rc; +} + +/* + * init_module: + */ + +#ifdef MODULE +int init_module(void) +{ + int rc = 0; +#ifdef DEBUG + printk("debug_module_init: \n"); +#endif + rc = debug_init(); + if (rc) + printk(KERN_INFO "debug: an error occurred with debug_init\n"); + return rc; +} + +/* + * cleanup_module: + */ + +void cleanup_module(void) +{ +#ifdef DEBUG + printk("debug_cleanup_module: \n"); +#endif + debug_delete_proc_dir_entry(&proc_root, debug_proc_root_entry); + return; +} + +#endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/ebcdic.c linux.ac/arch/s390/kernel/ebcdic.c --- linux-2.4.0/arch/s390/kernel/ebcdic.c Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/kernel/ebcdic.c Fri Jan 5 00:00:32 2001 @@ -161,7 +161,156 @@ /* - * EBCDIC 037 conversion table: + * ASCII (IBM PC 437) -> EBCDIC 500 + */ +__u8 _ascebc_500[256] = +{ + /*00 NUL SOH STX ETX EOT ENQ ACK BEL */ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, + /*08 BS HT LF VT FF CR SO SI */ + /* ->NL */ + 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /*10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, + /*18 CAN EM SUB ESC FS GS RS US */ + /* ->IGS ->IRS ->IUS */ + 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, + /*20 SP ! " # $ % & ' */ + 0x40, 0x4F, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, + /*28 ( ) * + , - . / */ + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + /*30 0 1 2 3 4 5 6 7 */ + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + /*38 8 9 : ; < = > ? */ + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + /*40 @ A B C D E F G */ + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + /*48 H I J K L M N O */ + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + /*50 P Q R S T U V W */ + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + /*58 X Y Z [ \ ] ^ _ */ + 0xE7, 0xE8, 0xE9, 0x4A, 0xE0, 0x5A, 0x5F, 0x6D, + /*60 ` a b c d e f g */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /*68 h i j k l m n o */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + /*70 p q r s t u v w */ + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + /*78 x y z { | } ~ DL */ + 0xA7, 0xA8, 0xA9, 0xC0, 0xBB, 0xD0, 0xA1, 0x07, + /*80*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*88*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*90*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*98*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*A0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*A8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*B0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*B8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*C0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*C8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*D0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*D8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*E0 sz */ + 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*E8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*F0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*F8*/ + 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF +}; + +/* + * EBCDIC 500 -> ASCII (IBM PC 437) + */ +__u8 _ebcasc_500[256] = +{ + /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ + 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, + /* 0x08 -GE -SPS -RPT VT FF CR SO SI */ + 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC + -ENP ->LF */ + 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07, + /* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB + -IUS */ + 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + /* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC + -INP */ + 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, + /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL + -SW */ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, + /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ + 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, + /* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */ + 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A, + /* 0x40 SP RSP ä ---- */ + 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86, + /* 0x48 [ . < ( + ! */ + 0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, + /* 0x50 & ---- */ + 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07, + /* 0x58 ß ] $ * ) ; ^ */ + 0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + /* 0x60 - / ---- Ä ---- ---- ---- */ + 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, + /* 0x68 ---- , % _ > ? */ + 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + /* 0x70 ---- ---- ---- ---- ---- ---- ---- */ + 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + /* 0x78 * ` : # @ ' = " */ + 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + /* 0x80 * a b c d e f g */ + 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + /* 0x88 h i ---- ---- ---- */ + 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1, + /* 0x90 ° j k l m n o p */ + 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + /* 0x98 q r ---- ---- */ + 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07, + /* 0xA0 ~ s t u v w x */ + 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + /* 0xA8 y z ---- ---- ---- ---- */ + 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07, + /* 0xB0 ---- § ---- */ + 0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC, + /* 0xB8 ---- | ---- ---- ---- ---- */ + 0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07, + /* 0xC0 { A B C D E F G */ + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 0xC8 H I ---- ö ---- */ + 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07, + /* 0xD0 } J K L M N O P */ + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + /* 0xD8 Q R ---- ü */ + 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98, + /* 0xE0 \ S T U V W X */ + 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + /* 0xE8 Y Z ---- Ö ---- ---- ---- */ + 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07, + /* 0xF0 0 1 2 3 4 5 6 7 */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */ + 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 +}; + + +/* + * EBCDIC 037/500 conversion table: * from upper to lower case */ __u8 _ebc_tolower[256] = @@ -202,7 +351,7 @@ /* - * EBCDIC 037 conversion table: + * EBCDIC 037/500 conversion table: * from lower to upper case */ __u8 _ebc_toupper[256] = diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/entry.S linux.ac/arch/s390/kernel/entry.S --- linux-2.4.0/arch/s390/kernel/entry.S Fri Aug 11 22:29:05 2000 +++ linux.ac/arch/s390/kernel/entry.S Fri Jan 5 00:00:32 2001 @@ -81,6 +81,7 @@ flags = 4 sigpending = 8 need_resched = 24 +tsk_ptrace = 28 processor = 60 /* PSW related defines */ @@ -88,6 +89,13 @@ enable = 0x03 daton = 0x04 +/* + * Base Address of this Module --- saved in __LC_ENTRY_BASE + */ + .globl entry_base +entry_base: + +#define BASED(name) name-entry_base(%r13) #if 0 /* some code left lying around in case we need a @@ -118,39 +126,37 @@ */ #define SAVE_ALL(psworg) \ - st %r15,__LC_SAVE_AREA ; \ + stm %r13,%r15,__LC_SAVE_AREA ; \ + stam %a2,%a4,__LC_SAVE_AREA+12 ; \ + basr %r13,0 ; /* temp base pointer */ \ + l %r13,.Lentry_base-.(%r13) ; /* load &entry_base to %r13 */ \ tm psworg+1,0x01 ; /* test problem state bit */ \ - jz 0f ; /* skip stack setup save */ \ + bz BASED(.+12) ; /* skip stack setup save */ \ l %r15,__LC_KERNEL_STACK ; /* problem state -> load ksp */ \ -0: ahi %r15,-SP_SIZE ; /* make room for registers & psw */ \ - srl %r15,3 ; \ - sll %r15,3 ; /* align stack pointer to 8 */ \ - stm %r0,%r14,SP_R0(%r15) ; /* store gprs 0-14 to kernel stack */ \ + lam %a2,%a4,BASED(.Lc_ac) ; /* set ac.reg. 2 to primary space */ \ + /* and access reg. 4 to home space */ \ +0: s %r15,BASED(.Lc_spsize); /* make room for registers & psw */ \ + n %r15,BASED(.Lc0xfffffff8) ; /* align stack pointer to 8 */ \ + stm %r0,%r12,SP_R0(%r15) ; /* store gprs 0-12 to kernel stack */ \ st %r2,SP_ORIG_R2(%r15) ; /* store original content of gpr 2 */ \ - mvc SP_RF(4,%r15),__LC_SAVE_AREA ; /* move R15 to stack */ \ + mvc SP_RD(12,%r15),__LC_SAVE_AREA ; /* move R13-R15 to stack */ \ stam %a0,%a15,SP_AREGS(%r15) ; /* store access registers to kst. */ \ + mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 ; /* store ac. regs */ \ mvc SP_PSW(8,%r15),psworg ; /* move user PSW to stack */ \ - lhi %r0,psworg ; /* store trap indication */ \ + la %r0,psworg ; /* store trap indication */ \ st %r0,SP_TRAP(%r15) ; \ - xc 0(4,%r15),0(%r15) ; /* clear back chain */ \ - tm psworg+1,0x01 ; /* kmod.c .wishes the set_fs & gs */ \ - jz 1f ; /* to work across syscalls */ \ - slr %r0,%r0 ; \ - sar %a2,%r0 ; /* set ac.reg. 2 to primary space */ \ - lhi %r0,1 ; \ - sar %a4,%r0 ; /* set access reg. 4 to home space */ \ -1: + xc 0(4,%r15),0(%r15) ; /* clear back chain */ #define RESTORE_ALL \ - mvc __LC_RETURN_PSW(8,0),SP_PSW(%r15) ; /* move user PSW to lowcore */ \ - lam %a0,%a15,SP_AREGS(%r15) ; /* load the access registers */ \ - lm %r0,%r15,SP_R0(%r15) ; /* load gprs 0-15 of user */ \ - ni __LC_RETURN_PSW+1(0),0xfd ; /* clear wait state bit */ \ - lpsw __LC_RETURN_PSW /* back to caller */ + mvc __LC_RETURN_PSW(8),SP_PSW(%r15) ; /* move user PSW to lowcore */ \ + lam %a0,%a15,SP_AREGS(%r15) ; /* load the access registers */ \ + lm %r0,%r15,SP_R0(%r15) ; /* load gprs 0-15 of user */ \ + ni __LC_RETURN_PSW+1,0xfd ; /* clear wait state bit */ \ + lpsw __LC_RETURN_PSW /* back to caller */ #define GET_CURRENT /* load pointer to task_struct to R9 */ \ - lhi %r9,-8192 ; \ - nr %r9,15 + lr %r9,%r15 ; \ + n %r9,BASED(.Lc0xffffe000) /* @@ -162,22 +168,24 @@ */ .globl resume resume: + basr %r1,0 +resume_base: l %r4,_TSS_PTREGS(%r3) tm SP_PSW-SP_PTREGS(%r4),0x40 # is the new process using per ? - jz RES_DN1 # if not we're fine - stctl %r9,%r11,24(%r15) # We are using per stuff + bz resume_noper-resume_base(%r1) # if not we're fine + stctl %r9,%r11,24(%r15) # We are using per stuff clc _TSS_PER(12,%r3),24(%r15) - je RES_DN1 # we got away without bashing TLB's - lctl %c9,%c11,_TSS_PER(%r3) # Nope we didn't -RES_DN1: + be resume_noper-resume_base(%r1) # we got away w/o bashing TLB's + lctl %c9,%c11,_TSS_PER(%r3) # Nope we didn't +resume_noper: stm %r6,%r15,24(%r15) # store resume registers of prev task st %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp - lhi %r0,-8192 - nr %r0,%r15 + lr %r0,%r15 + n %r0,.Lc0xffffe000-resume_base(%r1) l %r15,_TSS_KSP(%r3) # load kernel stack ptr from next->tss.ksp - lhi %r1,8191 + l %r1,.Lc8191-resume_base(%r1) or %r1,%r15 - ahi %r1,1 + la %r1,1(%r1) st %r1,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack stam %a2,%a2,_TSS_AR2(%r2) # store kernel access reg. 2 stam %a4,%a4,_TSS_AR4(%r2) # store kernel access reg. 4 @@ -192,38 +200,19 @@ * are executed with interrupts enabled. */ -sysc_lit: - sysc_do_signal: .long do_signal - sysc_do_softirq: .long do_softirq - sysc_schedule: .long schedule - sysc_trace: .long syscall_trace -#ifdef CONFIG_SMP - sysc_schedtail: .long schedule_tail -#endif - sysc_clone: .long sys_clone - sysc_fork: .long sys_fork - sysc_vfork: .long sys_vfork - sysc_sigreturn: .long sys_sigreturn - sysc_rt_sigreturn: .long sys_rt_sigreturn - sysc_execve: .long sys_execve - sysc_sigsuspend: .long sys_sigsuspend - sysc_rt_sigsuspend: .long sys_rt_sigsuspend - .globl system_call system_call: SAVE_ALL(0x20) - XC SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) + xc SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) pgm_system_call: - basr %r13,0 - ahi %r13,sysc_lit-. # setup base pointer R13 to sysc_lit slr %r8,%r8 # gpr 8 is call save (-> tracesys) ic %r8,0x8B # get svc number from lowcore stosm 24(%r15),0x03 # reenable interrupts GET_CURRENT # load pointer to task_struct to R9 sll %r8,2 - l %r8,sys_call_table-sysc_lit(8,%r13) # get address of system call - tm flags+3(%r9),0x20 # PF_TRACESYS - jnz sysc_tracesys + l %r8,sys_call_table-entry_base(8,%r13) # get address of system call + tm tsk_ptrace+3(%r9),0x02 # PT_TRACESYS + bnz BASED(sysc_tracesys) basr %r14,%r8 # call sys_xxxx st %r2,SP_R2(%r15) # store return value (change R2 on stack) # ATTENTION: check sys_execve_glue before @@ -232,24 +221,24 @@ sysc_return: GET_CURRENT # load pointer to task_struct to R9 tm SP_PSW+1(%r15),0x01 # returning to user ? - jno sysc_leave # no-> skip bottom half, resched & signal + bno BASED(sysc_leave) # no-> skip bottom half, resched & signal # # check, if bottom-half has to be done # l %r0,__LC_IRQ_STAT # get softirq_active n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask - jnz sysc_handle_bottom_half + bnz BASED(sysc_handle_bottom_half) # # check, if reschedule is needed # sysc_return_bh: icm %r0,15,need_resched(%r9) # get need_resched from task_struct - jnz sysc_reschedule + bnz BASED(sysc_reschedule) icm %r0,15,sigpending(%r9) # get sigpending from task_struct - jnz sysc_signal_return + bnz BASED(sysc_signal_return) sysc_leave: icm %r0,15,SP_SVC_STEP(%r15) # get sigpending from task_struct - jnz pgm_svcret + bnz BASED(pgm_svcret) stnsm 24(%r15),disable # disable I/O and ext. interrupts RESTORE_ALL @@ -259,24 +248,24 @@ sysc_signal_return: la %r2,SP_PTREGS(%r15) # load pt_regs sr %r3,%r3 # clear *oldset - l %r1,sysc_do_signal-sysc_lit(%r13) - la %r14,sysc_leave-sysc_lit(%r13) + l %r1,BASED(.Ldo_signal) + la %r14,BASED(sysc_leave) br %r1 # return point is sysc_leave # # call trace before and after sys_call # sysc_tracesys: - l %r1,sysc_trace-sysc_lit(%r13) - lhi %r2,-ENOSYS + l %r1,BASED(.Ltrace) + l %r2,BASED(.Lc_ENOSYS) st %r2,SP_R2(%r15) # give sysc_trace an -ENOSYS retval basr %r14,%r1 lm %r3,%r6,SP_R3(%r15) l %r2,SP_ORIG_R2(%r15) basr %r14,%r8 # call sys_xxx st %r2,SP_R2(%r15) # store return value - l %r1,sysc_trace-sysc_lit(%r13) - la %r14,sysc_return-sysc_lit(%r13) + l %r1,BASED(.Ltrace) + la %r14,BASED(sysc_return) br %r1 # return point is sysc_return @@ -285,16 +274,16 @@ # is zero # sysc_handle_bottom_half: - l %r1,sysc_do_softirq-sysc_lit(%r13) - la %r14,sysc_return_bh-sysc_lit(%r13) + l %r1,BASED(.Ldo_softirq) + la %r14,BASED(sysc_return_bh) br %r1 # call do_softirq # # call schedule with sysc_return as return-address # sysc_reschedule: - l %r1,sysc_schedule-sysc_lit(%r13) - la %r14,sysc_return-sysc_lit(%r13) + l %r1,BASED(.Lschedule) + la %r14,BASED(sysc_return) br %r1 # call scheduler, return to sysc_return # @@ -303,17 +292,17 @@ .globl ret_from_fork ret_from_fork: basr %r13,0 - ahi %r13,sysc_lit-. # setup base pointer R13 to $SYSCDAT + l %r13,.Lentry_base-.(%r13) # setup base pointer to &entry_base GET_CURRENT # load pointer to task_struct to R9 stosm 24(%r15),0x03 # reenable interrupts sr %r0,%r0 # child returns 0 st %r0,SP_R2(%r15) # store return value (change R2 on stack) #ifdef CONFIG_SMP - l %r1,sysc_schedtail-sysc_lit(%r13) - la %r14,sysc_return-sysc_lit(%r13) + l %r1,BASED(.Lschedtail) + la %r14,BASED(sysc_return) br %r1 # call schedule_tail, return to sysc_return #else - j sysc_return + b BASED(sysc_return) #endif # @@ -324,22 +313,22 @@ # sys_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,sysc_clone-sysc_lit(%r13) + l %r1,BASED(.Lclone) br %r1 # branch to sys_clone sys_fork_glue: la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,sysc_fork-sysc_lit(%r13) + l %r1,BASED(.Lfork) br %r1 # branch to sys_fork sys_vfork_glue: la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,sysc_vfork-sysc_lit(%r13) + l %r1,BASED(.Lvfork) br %r1 # branch to sys_vfork sys_execve_glue: la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,sysc_execve-sysc_lit(%r13) + l %r1,BASED(.Lexecve) lr %r12,%r14 # save return address basr %r14,%r1 # call sys_execve ltr %r2,%r2 # check if execve failed @@ -349,12 +338,12 @@ sys_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,sysc_sigreturn-sysc_lit(%r13) + l %r1,BASED(.Lsigreturn) br %r1 # branch to sys_sigreturn sys_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,sysc_rt_sigreturn-sysc_lit(%r13) + l %r1,BASED(.Lrt_sigreturn) br %r1 # branch to sys_sigreturn # @@ -369,7 +358,7 @@ lr %r4,%r3 # move history1 parameter lr %r3,%r2 # move history0 parameter la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - l %r1,sysc_sigsuspend-sysc_lit(%r13) + l %r1,BASED(.Lsigsuspend) la %r14,4(%r14) # skip store of return value br %r1 # branch to sys_sigsuspend @@ -377,10 +366,15 @@ lr %r4,%r3 # move sigsetsize parameter lr %r3,%r2 # move unewset parameter la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter - l %r1,sysc_rt_sigsuspend-sysc_lit(%r13) + l %r1,BASED(.Lrt_sigsuspend) la %r14,4(%r14) # skip store of return value br %r1 # branch to sys_rt_sigsuspend +sys_sigaltstack_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs as parameter + l %r1,BASED(.Lsigaltstack) + br %r1 # branch to sys_sigreturn + .globl sys_call_table sys_call_table: .long sys_ni_syscall /* 0 */ @@ -459,7 +453,7 @@ .long sys_sigpending .long sys_sethostname .long sys_setrlimit /* 75 */ - .long sys_getrlimit + .long sys_old_getrlimit .long sys_getrusage .long sys_gettimeofday .long sys_settimeofday @@ -569,13 +563,13 @@ .long sys_getcwd .long sys_capget .long sys_capset /* 185 */ - .long sys_sigaltstack + .long sys_sigaltstack_glue .long sys_sendfile .long sys_ni_syscall /* streams1 */ .long sys_ni_syscall /* streams2 */ .long sys_vfork_glue /* 190 */ .long sys_getrlimit - .long sys_ni_syscall /* FIXME: problem with sys_mmap2: 6 parms */ + .long sys_mmap2 .long sys_truncate64 .long sys_ftruncate64 .long sys_stat64 /* 195 */ @@ -604,7 +598,8 @@ .long sys_mincore .long sys_madvise .long sys_getdents64 /* 220 */ - .rept 255-220 + .long sys_fcntl64 + .rept 255-221 .long sys_ni_syscall .endr @@ -612,13 +607,6 @@ * Program check handler routine */ -pgm_lit: - pgm_handle_per: .long handle_per_exception - pgm_jump_table: .long pgm_check_table - pgm_sysc_ret: .long sysc_return - pgm_sysc_lit: .long sysc_lit - pgm_do_signal: .long do_signal - .globl pgm_check_handler pgm_check_handler: /* @@ -634,110 +622,131 @@ * we just ignore the PER event (FIXME: is there anything we have to do * for LPSW?). */ + stm %r13,%r15,__LC_SAVE_AREA + stam %a2,%a4,__LC_SAVE_AREA+12 + basr %r13,0 # temp base pointer + l %r13,.Lentry_base-.(%r13)# load &entry_base to %r13 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception - jz pgm_sv # skip if not + bz BASED(pgm_sv) # skip if not tm __LC_PGM_OLD_PSW,0x40 # test if per event recording is on - jnz pgm_sv # skip if it is + bnz BASED(pgm_sv) # skip if it is # ok its one of the special cases, now we need to find out which one clc __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW - je pgm_svcper + be BASED(pgm_svcper) # no interesting special case, ignore PER event - lpsw 0x28 + lm %r13,%r15,__LC_SAVE_AREA + lpsw 0x28 # it was a single stepped SVC that is causing all the trouble pgm_svcper: - SAVE_ALL(0x20) + tm 0x21,0x01 # test problem state bit + bz BASED(.+12) # skip stack & access regs setup + l %r15,__LC_KERNEL_STACK # problem state -> load ksp + lam %a2,%a4,BASED(.Lc_ac) # set ac.reg. 2 to primary space + # and access reg. 4 to home space + s %r15,BASED(.Lc_spsize) # make room for registers & psw + n %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8 + stm %r0,%r12,SP_R0(%r15) # store gprs 0-12 to kernel stack + st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 + mvc SP_RD(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack + stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst. + mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs + mvc SP_PSW(8,%r15),0x20 # move user PSW to stack + la %r0,0x20 # store trap indication + st %r0,SP_TRAP(%r15) + xc 0(4,%r15),0(%r15) # clear back chain mvi SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero mvc SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information - j pgm_system_call # now do the svc + b BASED(pgm_system_call) # now do the svc pgm_svcret: - lh %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack - lhi %r0,0x28 - st %r0,SP_TRAP(%r15) # set new trap indicator + mvi SP_TRAP+3(%r15),0x28 # set trap indication back to pgm_chk + lh %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack xc SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) - basr %r13,0 - ahi %r13,pgm_lit-. # setup base pointer - j pgm_no_sv + b BASED(pgm_no_sv) pgm_sv: - SAVE_ALL(0x28) - XC SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) - basr %r13,0 - ahi %r13,pgm_lit-. # setup base pointer R13 to $PGMDAT + tm 0x29,0x01 # test problem state bit + bz BASED(.+12) # skip stack & access regs setup + l %r15,__LC_KERNEL_STACK # problem state -> load ksp + lam %a2,%a4,BASED(.Lc_ac) # set ac.reg. 2 to primary space + # and access reg. 4 to home space + s %r15,BASED(.Lc_spsize) # make room for registers & psw + n %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8 + stm %r0,%r12,SP_R0(%r15) # store gprs 0-12 to kernel stack + st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 + mvc SP_RD(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack + stam %a0,%a15,SP_AREGS(%r15) # store access registers to kst. + mvc SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs + mvc SP_PSW(8,%r15),0x28 # move user PSW to stack + la %r0,0x28 # store trap indication + st %r0,SP_TRAP(%r15) + xc 0(4,%r15),0(%r15) # clear back chain + xc SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15) lh %r7,__LC_PGM_ILC # load instruction length pgm_no_sv: lh %r8,__LC_PGM_INT_CODE # N.B. saved int code used later KEEP it stosm 24(%r15),0x03 # reenable interrupts lr %r3,%r8 - lhi %r0,0x7f + la %r0,0x7f nr %r3,%r0 # clear per-event-bit - je pgm_dn # none of Martins exceptions occured bypass - l %r9,pgm_jump_table-pgm_lit(%r13) + be BASED(pgm_dn) # none of Martins exceptions occured bypass + l %r9,BASED(.Ljump_table) sll %r3,2 l %r9,0(%r3,%r9) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area srl %r3,2 - chi %r3,0x4 # protection-exception ? - jne pgm_go # if not, + cl %r3,BASED(.Lc4) # protection-exception ? + bne BASED(pgm_go) # if not, l %r5,SP_PSW+4(15) # load psw addr sr %r5,%r7 # substract ilc from psw st %r5,SP_PSW+4(15) # store corrected psw addr pgm_go: basr %r14,%r9 # branch to interrupt-handler -pgm_dn: lhi %r0,0x80 +pgm_dn: la %r0,0x80 nr %r8,%r0 # check for per exception - je pgm_return + be BASED(pgm_return) la %r2,SP_PTREGS(15) # address of register-save area - l %r9,pgm_handle_per-pgm_lit(%r13) # load adr. of per handler - l %r14,pgm_sysc_ret-pgm_lit(%r13) # load adr. of system return - l %r13,pgm_sysc_lit-pgm_lit(%r13) + l %r9,BASED(.Lhandle_per) # load adr. of per handler + la %r14,BASED(sysc_return) # load adr. of system return br %r9 # branch to handle_per_exception + # # the backend code is the same as for sys-call # pgm_return: - l %r14,pgm_sysc_ret-pgm_lit(%r13) - l %r13,pgm_sysc_lit-pgm_lit(%r13) - br %r14 + b BASED(sysc_return) /* * IO interrupt handler routine */ -io_lit: - io_do_IRQ: .long do_IRQ - io_schedule: .long schedule - io_do_signal: .long do_signal - io_do_softirq: .long do_softirq - .globl io_int_handler io_int_handler: SAVE_ALL(0x38) - basr %r13,0 - ahi %r13,io_lit-. # setup base pointer R13 to $IODAT la %r2,SP_PTREGS(%r15) # address of register-save area sr %r3,%r3 icm %r3,%r3,__LC_SUBCHANNEL_NR # load subchannel nr & extend to int l %r4,__LC_IO_INT_PARM # load interuption parm - l %r9,io_do_IRQ-io_lit(%r13) # load address of do_IRQ + l %r5,__LC_IO_INT_WORD # load interuption word + l %r9,BASED(.Ldo_IRQ) # load address of do_IRQ basr %r14,%r9 # branch to standard irq handler io_return: GET_CURRENT # load pointer to task_struct to R9 tm SP_PSW+1(%r15),0x01 # returning to user ? - jz io_leave # no-> skip resched & signal + bz BASED(io_leave) # no-> skip resched & signal stosm 24(%r15),0x03 # reenable interrupts # # check, if bottom-half has to be done # l %r0,__LC_IRQ_STAT # get softirq_active n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask - jnz io_handle_bottom_half + bnz BASED(io_handle_bottom_half) io_return_bh: # # check, if reschedule is needed # icm %r0,15,need_resched(%r9) # get need_resched from task_struct - jnz io_reschedule + bnz BASED(io_reschedule) icm %r0,15,sigpending(%r9) # get sigpending from task_struct - jnz io_signal_return + bnz BASED(io_signal_return) io_leave: stnsm 24(%r15),disable # disable I/O and ext. interrupts RESTORE_ALL @@ -747,16 +756,16 @@ # is zero # io_handle_bottom_half: - l %r1,io_do_softirq-io_lit(%r13) - la %r14,io_return_bh-io_lit(%r13) + l %r1,BASED(.Ldo_softirq) + la %r14,BASED(io_return_bh) br %r1 # call do_softirq # # call schedule with io_return as return-address # io_reschedule: - l %r1,io_schedule-io_lit(%r13) - la %r14,io_return-io_lit(%r13) + l %r1,BASED(.Lschedule) + la %r14,BASED(io_return) br %r1 # call scheduler, return to io_return # @@ -765,103 +774,46 @@ io_signal_return: la %r2,SP_PTREGS(%r15) # load pt_regs sr %r3,%r3 # clear *oldset - l %r1,io_do_signal-io_lit(%r13) - la %r14,io_leave-io_lit(%r13) + l %r1,BASED(.Ldo_signal) + la %r14,BASED(io_leave) br %r1 # return point is io_leave /* * External interrupt handler routine */ -ext_lit: - ext_timer_int: .long do_timer_interrupt -#ifdef CONFIG_SMP - ext_call_int: .long do_ext_call_interrupt -#endif -#ifdef CONFIG_HWC - ext_hwc_int: .long do_hwc_interrupt -#endif -#ifdef CONFIG_MDISK - ext_mdisk_int: .long do_mdisk_interrupt -#endif -#ifdef CONFIG_IUCV - ext_iucv_int: .long do_iucv_interrupt -#endif - ext_io_lit: .long io_lit - ext_io_return: .long io_return - .globl ext_int_handler ext_int_handler: SAVE_ALL(0x18) - basr %r13,0 - ahi %r13,ext_lit-. # setup base pointer R13 to $EXTDAT la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # error code -#ifdef CONFIG_SMP - chi %r3,0x1202 # EXTERNAL_CALL - jne ext_no_extcall - l %r9,ext_call_int-ext_lit(%r13) # load ext_call_interrupt - l %r14,ext_io_return-ext_lit(%r13) - l %r13,ext_io_lit-ext_lit(%r13) - br %r9 # branch to ext call handler -ext_no_extcall: -#endif - chi %r3,0x1004 # CPU_TIMER - jne ext_no_timer - l %r9,ext_timer_int-ext_lit(%r13) # load timer_interrupt - l %r14,ext_io_return-ext_lit(%r13) - l %r13,ext_io_lit-ext_lit(%r13) - br %r9 # branch to ext call handler -ext_no_timer: -#ifdef CONFIG_HWC - chi %r3,0x2401 # HWC interrupt - jne ext_no_hwc - l %r9,ext_hwc_int-ext_lit(%r13) # load addr. of hwc routine - l %r14,ext_io_return-ext_lit(%r13) - l %r13,ext_io_lit-ext_lit(%r13) - br %r9 # branch to ext call handler -ext_no_hwc: -#endif -#ifdef CONFIG_MDISK - chi %r3,0x2603 # diag 250 (VM) interrupt - jne ext_no_mdisk - l %r9,ext_mdisk_int-ext_lit(%r13) - l %r14,ext_io_return-ext_lit(%r13) - l %r13,ext_io_lit-ext_lit(%r13) - br %r9 # branch to ext call handler -ext_no_mdisk: -#endif -#ifdef CONFIG_IUCV - chi %r3,0x4000 # diag 250 (VM) interrupt - jne ext_no_iucv - l %r9,ext_iucv_int-ext_lit(%r13) - l %r14,ext_io_return-ext_lit(%r13) - l %r13,ext_io_lit-ext_lit(%r13) - br %r9 # branch to ext call handler -ext_no_iucv: -#endif - - l %r14,ext_io_return-ext_lit(%r13) - l %r13,ext_io_lit-ext_lit(%r13) - br %r14 # use backend code of io_int_handler + lr %r1,%r3 # calculate index = code & 0xff + n %r1,BASED(.Lc0xff) + sll %r1,2 + l %r9,BASED(.Lext_hash) + l %r9,0(%r1,%r9) # get first list entry for hash value + ltr %r9,%r9 # == NULL ? + bz BASED(io_return) # yes, nothing to do, exit +ext_int_loop: + ch %r3,8(%r9) # compare external interrupt code + be BASED(ext_int_found) + icm %r9,15,0(%r9) # next list entry + bnz BASED(ext_int_loop) + b BASED(io_return) +ext_int_found: + l %r9,4(%r9) # get handler address + la %r14,BASED(io_return) + br %r9 # branch to ext call handler /* * Machine check handler routines */ -mcck_lit: - mcck_crw_pending: .long do_crw_pending - .globl mcck_int_handler mcck_int_handler: SAVE_ALL(0x30) - basr %r13,0 - ahi %r13,mcck_lit-. # setup base pointer R13 to $MCCKDAT - tm __LC_MCCK_CODE+1,0x40 - jno mcck_no_crw - l %r1,mcck_crw_pending-mcck_lit(%r13) - basr %r14,%r1 # call do_crw_pending -mcck_no_crw: + l %r1,BASED(.Ls390_mcck) + basr %r14,%r1 # call machine check handler mcck_return: RESTORE_ALL @@ -876,11 +828,11 @@ lam %a0,%a15,__LC_AREGS_SAVE_AREA stosm 0(%r15),daton # now we can turn dat on lm %r6,%r15,24(%r15) # load registers from clone - bras %r14,restart_go - .long start_secondary -restart_go: - l %r14,0(%r14) + basr %r14,0 + l %r14,restart_addr-.(%r14) br %r14 # branch to start_secondary +restart_addr: + .long start_secondary #else /* * If we do not run with SMP enabled, let the new CPU crash ... @@ -894,5 +846,50 @@ restart_crash: .long 0x000a0000,0x00000000 restart_go: +#endif + +/* + * Integer constants + */ + .align 4 +.Lc0xfffffff8: .long -8 # to align stack pointer to 8 +.Lc0xffffe000: .long -8192 # to round stack pointer to &task_struct +.Lc8191: .long 8191 +.Lc_spsize: .long SP_SIZE +.Lc_ac: .long 0,0,1 +.Lc_ENOSYS: .long -ENOSYS +.Lc4: .long 4 +.Lc0x1202: .long 0x1202 +.Lc0x1004: .long 0x1004 +.Lc0x2401: .long 0x2401 +.Lc0x4000: .long 0x4000 +.Lc0xff: .long 0xff + +/* + * Symbol constants + */ +.Ls390_mcck: .long s390_do_machine_check +.Ldo_IRQ: .long do_IRQ +.Ldo_signal: .long do_signal +.Ldo_softirq: .long do_softirq +.Lentry_base: .long entry_base +.Lext_hash: .long ext_int_hash +.Lhandle_per: .long handle_per_exception +.Ljump_table: .long pgm_check_table +.Lschedule: .long schedule +.Lclone: .long sys_clone +.Lexecve: .long sys_execve +.Lfork: .long sys_fork +.Lrt_sigreturn:.long sys_rt_sigreturn +.Lrt_sigsuspend: + .long sys_rt_sigsuspend +.Lsigreturn: .long sys_sigreturn +.Lsigsuspend: .long sys_sigsuspend +.Lsigaltstack: .long sys_sigaltstack +.Ltrace: .long syscall_trace +.Lvfork: .long sys_vfork + +#ifdef CONFIG_SMP +.Lschedtail: .long schedule_tail #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/head.S linux.ac/arch/s390/kernel/head.S --- linux-2.4.0/arch/s390/kernel/head.S Fri May 12 19:41:44 2000 +++ linux.ac/arch/s390/kernel/head.S Fri Jan 5 00:00:32 2001 @@ -2,20 +2,29 @@ * arch/s390/kernel/head.S * * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Hartmut Penner (hp@de.ibm.com), * Martin Schwidefsky (schwidefsky@de.ibm.com), + * Rob van der Heij (rvdhei@iae.nl) * - * There are 4 different IPL methods + * There are 5 different IPL methods * 1) load the image directly into ram at address 0 and do an PSW restart * 2) linload will load the image from address 0x10000 to memory 0x10000 * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated) * 3) generate the tape ipl header, store the generated image on a tape * and ipl from it + * In case of SL tape you need to IPL 5 times to get past VOL1 etc * 4) generate the vm reader ipl header, move the generated image to the * VM reader (use option NOH!) and do a ipl from reader (VM only) + * 5) direct call of start by the SALIPL loader * We use the cpuid to distinguish between VM and native ipl * params for kernel are pushed to 0x10400 (see setup.h) + + Changes: + Okt 25 2000 + added code to skip HDR and EOF to allow SL tape IPL (5 retries) + changed first CCW from rewind to backspace block + */ #include @@ -24,40 +33,13 @@ #ifndef CONFIG_IPL .org 0 - .long 0x00080000,0x80000000+iplstart # Just a restart PSW - -iplstart: - l %r12,.Lparm # pointer to parameter area -# -# find out memory size -# - mvc 104(8,0),.Lpcmem0 # setup program check handler - slr %r2,%r2 - lhi %r3,1 - sll %r3,20 -.Lloop0: - l %r0,0(%r2) # test page - ar %r2,%r3 # add 1M - jnm .Lloop0 # r1 < 0x80000000 -> loop -.Lchkmem0: - n %r2,.L4malign0 # align to multiples of 4M - st %r2,MEMORY_SIZE-PARMAREA(%r12) # store memory size - slr %r2,%r2 - st %r2,INITRD_SIZE-PARMAREA(%r12) # null ramdisk - st %r2,INITRD_START-PARMAREA(%r12) - j start - -.Lparm: .long PARMAREA -.L4malign0:.long 0xffc00000 - .align 8 -.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 - + .long 0x00080000,0x80000000+startup # Just a restart PSW #else #ifdef CONFIG_IPL_TAPE #define IPL_BS 1024 .org 0 .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded - .long 0x07000000,0x60000001 # by ipl to addresses 0-23. + .long 0x27000000,0x60000001 # by ipl to addresses 0-23. .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). .long 0x00000000,0x00000000 # external old psw .long 0x00000000,0x00000000 # svc old psw @@ -74,92 +56,6 @@ .long 0x00080000,0x80000000+.Lioint # io new psw .org 0x100 -iplstart: - l %r1,0xb8 # load ipl subchannel number - lhi %r2,IPL_BS # load start address - bras %r14,.Lloader # load rest of ipl image - st %r1,__LC_IPLDEV # store ipl device number - l %r12,.Lparm # pointer to parameter area - -# -# find out memory size -# - mvc 104(8,0),.Lpcmem0 # setup program check handler - slr %r2,%r2 - lhi %r3,1 - sll %r3,20 -.Lloop0: - l %r0,0(%r2) # test page - ar %r2,%r3 # add 1M - jnm .Lloop0 # r1 < 0x80000000 -> loop -.Lchkmem0: - n %r2,.L4malign0 # align to multiples of 4M - st %r2,MEMORY_SIZE-PARMAREA(%r12) # store memory size - c %r2,.Lbigmem # more than 64 MB of memory ? - jl .Lmemok # if yes load ramdisk to 32 MB - mvc INITRD_START-PARMAREA(4,%r12),.Lrdstart -.Lmemok: - -# -# load parameter file from tape -# - l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp - bras %r14,.Lloader # load parameter file - ltr %r2,%r2 # got anything ? - jz .Lnopf - chi %r2,895 - jnh .Lnotrunc - lhi %r2,895 -.Lnotrunc: - l %r4,INITRD_START-PARMAREA(%r12) - la %r5,0(%r4,%r2) - lr %r3,%r2 -.Lidebc: - tm 0(%r5),0x80 # high order bit set ? - jo .Ldocv # yes -> convert from EBCDIC - ahi %r5,-1 - brct %r3,.Lidebc - j .Lnocv -.Ldocv: - l %r3,.Lcvtab - tr 0(256,%r4),0(%r3) # convert parameters to ascii - tr 256(256,%r4),0(%r3) - tr 512(256,%r4),0(%r3) - tr 768(122,%r4),0(%r3) -.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line - mvc 0(256,%r3),0(%r4) - mvc 256(256,%r3),256(%r4) - mvc 512(256,%r3),512(%r4) - mvc 768(122,%r3),768(%r4) - slr %r0,%r0 - j .Lcntlp -.Ldelspc: - ic %r0,0(%r2,%r3) - chi %r0,0x20 # is it a space ? - je .Lcntlp - ahi %r2,1 - j .Leolp -.Lcntlp: - brct %r2,.Ldelspc -.Leolp: - slr %r0,%r0 - stc %r0,0(%r2,%r3) # terminate buffer -.Lnopf: - -# -# load ramdisk from tape -# - l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk - bras %r14,.Lloader # load ramdisk - st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk - ltr %r2,%r2 - jnz .Lrdcont - st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it -.Lrdcont: -# -# everything loaded, go for it -# - j start # # subroutine for loading from tape # Paramters: @@ -173,32 +69,32 @@ lctl %c6,%c6,.Lcr6 slr %r2,%r2 .Lldlp: - lhi %r6,3 # 3 retries + la %r6,3 # 3 retries .Lssch: ssch 0(%r3) # load chunk of IPL_BS bytes - jnz .Llderr + bnz .Llderr .Lw4end: - bras %r14,.Lwait4io + bas %r14,.Lwait4io tm 8(%r5),0x82 # do we have a problem ? - jnz .Lrecov + bnz .Lrecov slr %r7,%r7 icm %r7,3,10(%r5) # get residual count lcr %r7,%r7 - ahi %r7,IPL_BS # IPL_BS-residual=#bytes read + la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read ar %r2,%r7 # add to total size tm 8(%r5),0x01 # found a tape mark ? - jnz .Ldone + bnz .Ldone l %r0,.Lccwread+4 # update CCW data addresses ar %r0,%r7 st %r0,.Lccwread+4 - j .Lldlp + b .Lldlp .Ldone: l %r14,.Lldret br %r14 # r2 contains the total size .Lrecov: - bras %r14,.Lsense # do the sensing - brct %r6,.Lssch # dec. retry count & branch - j .Llderr + bas %r14,.Lsense # do the sensing + bct %r6,.Lssch # dec. retry count & branch + b .Llderr # # Sense subroutine # @@ -206,11 +102,11 @@ st %r14,.Lsnsret la %r7,.Lorbsense ssch 0(%r7) # start sense command - jnz .Llderr - bras %r14,.Lwait4io + bnz .Llderr + bas %r14,.Lwait4io l %r14,.Lsnsret tm 8(%r5),0x82 # do we have a problem ? - jnz .Llderr + bnz .Llderr br %r14 # # Wait for interrupt subroutine @@ -219,13 +115,13 @@ lpsw .Lwaitpsw .Lioint: c %r1,0xb8 # compare subchannel number - jne .Lwait4io + bne .Lwait4io tsch 0(%r5) slr %r0,%r0 tm 8(%r5),0x82 # do we have a problem ? - jnz .Lwtexit + bnz .Lwtexit tm 8(%r5),0x04 # got device end ? - jz .Lwait4io + bz .Lwait4io .Lwtexit: br %r14 .Llderr: @@ -249,18 +145,12 @@ .Lcr6: .long 0xff000000 .align 8 .Lcrash:.long 0x000a0000,0x00000000 -.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 -.Lparm: .long PARMAREA -.L4malign0:.long 0xffc00000 -.Lbigmem:.long 0x04000000 -.Lrdstart:.long 0x02000000 .Lldret:.long 0 .Lsnsret: .long 0 -.Lcvtab:.long _ebcasc # ebcdic to ascii table - #endif /* CONFIG_IPL_TAPE */ #ifdef CONFIG_IPL_VM +#define IPL_BS 0x730 .org 0 .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded .long 0x02000018,0x60000050 # by ipl to addresses 0-23. @@ -287,103 +177,7 @@ .long 0x02000690,0x60000050 .long 0x020006e0,0x20000050 - .org 0xf0 -iplstart: - l %r1,0xb8 # load ipl subchannel number - lhi %r2,0x730 # load start address - bras %r14,.Lloader # load rest of ipl image - st %r1,__LC_IPLDEV # store ipl device number - l %r12,.Lparm # pointer to parameter area - -# -# find out memory size -# - mvc 104(8,0),.Lpcmem0 # setup program check handler - slr %r2,%r2 - lhi %r3,1 - sll %r3,20 -.Lloop0: - l %r0,0(%r2) # test page - ar %r2,%r3 # add 1M - jnm .Lloop0 # r1 < 0x80000000 -> loop -.Lchkmem0: - n %r2,.L4malign0 # align to multiples of 4M - st %r2,MEMORY_SIZE-PARMAREA(%r12) # store memory size - c %r2,.Lbigmem # more than 64 MB of memory ? - jl .Lmemok # if yes load ramdisk to 32 MB - mvc INITRD_START-PARMAREA(4,%r12),.Lrdstart -.Lmemok: - -# -# load parameter file from reader -# - l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp - bras %r14,.Lloader # load parameter file - ltr %r2,%r2 # got anything ? - jz .Lnopf - chi %r2,895 - jnh .Lnotrunc - lhi %r2,895 -.Lnotrunc: - l %r4,INITRD_START-PARMAREA(%r12) - la %r5,0(%r4,%r2) - lr %r3,%r2 -.Lidebc: - tm 0(%r5),0x80 # high order bit set ? - jo .Ldocv # yes -> convert from EBCDIC - ahi %r5,-1 - brct %r3,.Lidebc - j .Lnocv -.Ldocv: - l %r3,.Lcvtab - tr 0(256,%r4),0(%r3) # convert parameters to ascii - tr 256(256,%r4),0(%r3) - tr 512(256,%r4),0(%r3) - tr 768(122,%r4),0(%r3) -.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line - mvc 0(256,%r3),0(%r4) - mvc 256(256,%r3),256(%r4) - mvc 512(256,%r3),512(%r4) - mvc 768(122,%r3),768(%r4) - slr %r0,%r0 - j .Lcntlp -.Ldelspc: - ic %r0,0(%r2,%r3) - chi %r0,0x20 # is it a space ? - je .Lcntlp - ahi %r2,1 - j .Leolp -.Lcntlp: - brct %r2,.Ldelspc -.Leolp: - slr %r0,%r0 - stc %r0,0(%r2,%r3) # terminate buffer -.Lnopf: - -# -# load ramdisk from reader -# - l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk - bras %r14,.Lloader # load ramdisk - st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk - ltr %r2,%r2 - jnz .Lrdcont - st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it -.Lrdcont: - -# -# everything loaded, reset files in reader, then go for it -# - stidp __LC_CPUID # store cpuid - lh %r0,__LC_CPUID+4 # get cpu version - chi %r0,0x7490 # running on P/390 ? - je start # no -> skip reset - la %r2,.Lreset - lhi %r3,26 - .long 0x83230008 - j start - # # subroutine for loading cards from the reader # @@ -394,29 +188,29 @@ la %r7,20 .Linit: st %r2,4(%r6) # initialize CCW data addresses - ahi %r2,0x50 - ahi %r6,8 - brct 7,.Linit + la %r2,0x50(%r2) + la %r6,8(%r6) + bct 7,.Linit lctl %c6,%c6,.Lcr6 # set IO subclass mask slr %r2,%r2 .Lldlp: ssch 0(%r3) # load chunk of 1600 bytes - jnz .Llderr + bnz .Llderr .Lwait4irq: mvc __LC_IO_NEW_PSW(8),.Lnewpsw # set up IO interrupt psw lpsw .Lwaitpsw .Lioint: c %r1,0xb8 # compare subchannel number - jne .Lwait4irq + bne .Lwait4irq tsch 0(%r5) slr %r0,%r0 ic %r0,8(%r5) # get device status chi %r0,8 # channel end ? - je .Lcont + be .Lcont chi %r0,12 # channel end + device end ? - je .Lcont + be .Lcont l %r0,4(%r5) s %r0,8(%r3) # r0/8 = number of ccws executed @@ -436,9 +230,9 @@ ahi %r0,0x640 st %r0,4(%r6) ahi %r6,8 - brct 7,.Lincr + bct 7,.Lincr - j .Lldlp + b .Lldlp .Llderr: lpsw .Lcrash @@ -447,16 +241,7 @@ .Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .Lcr6: .long 0xff000000 .Lloadp:.long 0,0 -.Lparm: .long PARMAREA -.L4malign0:.long 0xffc00000 -.Lbigmem:.long 0x04000000 -.Lrdstart:.long 0x02000000 -.Lcvtab:.long _ebcasc # ebcdic to ascii table -.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 - .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 - .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" .align 8 -.Lpcmem0:.long 0x00080000,0x80000000 + .Lchkmem0 .Lcrash:.long 0x000a0000,0x00000000 .Lnewpsw: .long 0x00080000,0x80000000+.Lioint @@ -468,79 +253,330 @@ .long 0x02600050,0x00000000 .endr .long 0x02200050,0x00000000 - - .org 0x730 # end of the area loaded by the ipl channel program #endif /* CONFIG_IPL_VM */ +iplstart: + lh %r1,0xb8 # test if subchannel number + bct %r1,.Lnoload # is valid + l %r1,0xb8 # load ipl subchannel number + la %r2,IPL_BS # load start address + bas %r14,.Lloader # load rest of ipl image + st %r1,__LC_IPLDEV # store ipl device number + l %r12,.Lparm # pointer to parameter area + +# +# load parameter file from ipl device +# +.Lagain1: + l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp + bas %r14,.Lloader # load parameter file + ltr %r2,%r2 # got anything ? + bz .Lnopf + chi %r2,895 + bnh .Lnotrunc + la %r2,895 +.Lnotrunc: + l %r4,INITRD_START-PARMAREA(%r12) + clc 0(3,%r4),.L_hdr # if it is HDRx + bz .Lagain1 # skip dataset header + clc 0(3,%r4),.L_eof # if it is EOFx + bz .Lagain1 # skip dateset trailer + la %r5,0(%r4,%r2) + lr %r3,%r2 +.Lidebc: + tm 0(%r5),0x80 # high order bit set ? + bo .Ldocv # yes -> convert from EBCDIC + ahi %r5,-1 + bct %r3,.Lidebc + b .Lnocv +.Ldocv: + l %r3,.Lcvtab + tr 0(256,%r4),0(%r3) # convert parameters to ascii + tr 256(256,%r4),0(%r3) + tr 512(256,%r4),0(%r3) + tr 768(122,%r4),0(%r3) +.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line + mvc 0(256,%r3),0(%r4) + mvc 256(256,%r3),256(%r4) + mvc 512(256,%r3),512(%r4) + mvc 768(122,%r3),768(%r4) + slr %r0,%r0 + b .Lcntlp +.Ldelspc: + ic %r0,0(%r2,%r3) + chi %r0,0x20 # is it a space ? + be .Lcntlp + ahi %r2,1 + b .Leolp +.Lcntlp: + brct %r2,.Ldelspc +.Leolp: + slr %r0,%r0 + stc %r0,0(%r2,%r3) # terminate buffer +.Lnopf: + +# +# load ramdisk from ipl device +# +.Lagain2: + l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk + bas %r14,.Lloader # load ramdisk + st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk + ltr %r2,%r2 + bnz .Lrdcont + st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it +.Lrdcont: + l %r2,INITRD_START-PARMAREA(%r12) + + clc 0(3,%r2),.L_hdr # skip HDRx and EOFx + bz .Lagain2 + clc 0(3,%r2),.L_eof + bz .Lagain2 + +#ifdef CONFIG_IPL_VM +# +# reset files in VM reader +# + stidp __LC_CPUID # store cpuid + lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on P/390 ? + be start # no -> skip reset + la %r2,.Lreset + lhi %r3,26 + .long 0x83230008 +#endif + +# +# everything loaded, go for it +# +.Lnoload: + l %r1,.Lstartup + br %r1 + +.Lparm: .long PARMAREA +.Lstartup: .long startup +.Lcvtab:.long _ebcasc # ebcdic to ascii table +.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 + .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 + .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" +.L_eof: .long 0xc5d6c600 /* C'EOF' */ +.L_hdr: .long 0xc8c4d900 /* C'HDR' */ + #endif /* CONFIG_IPL */ # +# SALIPL loader support. Based on a patch by Rob van der Heij. +# This entry point is called directly from the SALIPL loader and +# doesn't need a builtin ipl record. +# + .org 0x800 + .globl start +start: + stm %r0,%r15,0x07b0 # store registers + basr %r12,%r0 +.base: + l %r11,.parm + l %r8,.cmd # pointer to command buffer + + ltr %r9,%r9 # do we have SALIPL parameters? + bp .sk8x8 + + mvc 0(64,%r8),0x00b0 # copy saved registers + xc 64(240-64,%r8),0(%r8) # remainder of buffer + tr 0(64,%r8),.lowcase + b .gotr +.sk8x8: + mvc 0(240,%r8),0(%r9) # copy iplparms into buffer +.gotr: + l %r10,.tbl # EBCDIC to ASCII table + tr 0(240,%r8),0(%r10) + stidp __LC_CPUID # Are we running on VM maybe + cli __LC_CPUID,0xff + bnz .test + .long 0x83300060 # diag 3,0,x'0060' - storage size + b .done +.test: + mvc 0x68(8),.pgmnw # set up pgm check handler + l %r2,.fourmeg + lr %r3,%r2 + bctr %r3,%r0 # 4M-1 +.loop: iske %r0,%r3 + ar %r3,%r2 +.pgmx: + sr %r3,%r2 + la %r3,1(%r3) +.done: + st %r3,MEMORY_SIZE-PARMAREA(%r11) + slr %r0,%r0 + st %r0,INITRD_SIZE-PARMAREA(%r11) + st %r0,INITRD_START-PARMAREA(%r11) + j startup # continue with startup +.tbl: .long _ebcasc # translate table +.cmd: .long COMMAND_LINE # address of command line buffer +.parm: .long PARMAREA +.fourmeg: .long 0x00400000 # 4M +.pgmnw: .long 0x00080000,.pgmx +.lowcase: + .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 + .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f + .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 + .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f + .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 + .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f + .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 + .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f + .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 + .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f + .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 + .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f + .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 + .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f + + .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 + .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f + .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 + .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f + .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 + .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf + .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 + .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf + .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg + .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf # hi + .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop + .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf # qr + .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 # ..stuvwx + .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef # yz + .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 + .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + +# # startup-code at 0x10000, running in real mode -# this is called either by the ipl loader or directly by PSW restart or linload +# this is called either by the ipl loader or directly by PSW restart +# or linload or SALIPL # .org 0x10000 - .globl start -start: basr %r13,0 # get base -.LPG1: lctl %c1,%c1,.Lpstd-.LPG1(%r13) # load pstd - lctl %c7,%c7,.Lpstd-.LPG1(%r13) # load sstd - lctl %c13,%c13,.Lpstd-.LPG1(%r13) # load hstd - lctl %c0,%c0,.Lcr0-.LPG1(%r13) # set CR0 +startup:basr %r13,0 # get base +.LPG1: lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers l %r12,.Lparm1-.LPG1(%r13) # pointer to parameter area # -# find out memory size. That is done in the ipl loader too but for -# ipl from dasd the size of the memory has to be detected too... +# find out memory size. # - icm %r0,15,MEMORY_SIZE-PARMAREA(%r12) - jnz .Lsizeok - mvc 104(8,0),.Lpcmem-.LPG1(%r13) # setup program check handler - slr %r1,%r1 + mvc 104(8),.Lpcmem-.LPG1(%r13) # setup program check handler lhi %r2,1 - sll %r2,20 + sll %r2,17 # test in increments of 128KB + lr %r1,%r2 + ahi %r1,-4 # test last word in the segment .Lloop: - l %r0,0(%r1) # test page - ar %r1,%r2 # add 1M - jnm .Lloop # r1 < 0x80000000 -> loop + l %r0,0(%r1) # test 128KB segment + st %r0,0(%r1) + ar %r1,%r2 # add 128KB + bnm .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop .Lchkmem: n %r1,.L4malign-.LPG1(%r13) # align to multiples of 4M st %r1,MEMORY_SIZE-PARMAREA(%r12) # store memory size .Lsizeok: # +# Now we have to move the ramdisk to a location approriate for the +# memory size. If we have more than 64 MB of memory we move it to 32MB +# to make room for the page tables set up by paging_init. +# + l %r1,MEMORY_SIZE-PARMAREA(%r12) + cl %r1,.Lbigmem-.LPG1(%r13) # memory < 64mb ? + bl .Lnomove-.LPG1(%r13) # if yes ramdisk @8MB is ok + icm %r4,15,INITRD_START-PARMAREA(%r12) + bz .Lnomove-.LPG1(%r13) + l %r2,.Lrdstart-.LPG1(%r13) # new address of ramdisk + st %r2,INITRD_START-PARMAREA(%r12) + l %r1,INITRD_SIZE-PARMAREA(%r12) + ar %r2,%r1 # we start moving at the end + ar %r4,%r1 # because new location > old location +.Lmove: lr %r0,%r2 # new - old is the maximum we can move + sr %r0,%r4 # because of overlapping + cr %r0,%r1 # we shouldn't move more than there is + bnh .Lnoend-.LPG1(%r13) + lr %r0,%r1 +.Lnoend:cl %r0,.Lmaxchunk-.LPG1(%r13) # mvcl can move 2^24-1 in one go + bnh .Lchunk-.LPG1(%r13) + l %r0,.Lmaxchunk-.LPG1(%r13) +.Lchunk:sr %r2,%r0 # make source & destination pointer + sr %r4,%r0 + lr %r3,%r0 # set source & destination length + lr %r5,%r0 + mvcl %r2,%r4 + sr %r2,%r0 # substract length again, since + sr %r4,%r0 # mvcl added it to the pointers + sr %r1,%r0 # substract chunk size from length + bnz .Lmove-.LPG1(%r13) +.Lnomove: + +# # find out if we are running under VM # stidp __LC_CPUID # store cpuid tm __LC_CPUID,0xff # running under VM ? - jno .Lnovm + bno .Lnovm-.LPG1(%r13) oi MACHINE_FLAGS+3-PARMAREA(%r12),1 # set VM flag .Lnovm: lh %r0,__LC_CPUID+4 # get cpu version chi %r0,0x7490 # running on a P/390 ? - jne .Lnop390 + bne .Lnop390-.LPG1(%r13) oi MACHINE_FLAGS+3-PARMAREA(%r12),4 # set P/390 flag .Lnop390: # # find out if we have an IEEE fpu # - mvc 104(8,0),.Lpcfpu-.LPG1(%r13) # setup program check handler + mvc 104(8),.Lpcfpu-.LPG1(%r13) # setup program check handler ld %f0,.Lflt0-.LPG1(%r13) # load (float) 0.0 ldr %f2,%f0 adbr %f0,%f2 # test IEEE add instruction oi MACHINE_FLAGS+3-PARMAREA(%r12),2 # set IEEE fpu flag .Lchkfpu: +# +# find out if we have the CSP instruction +# + mvc 104(8),.Lpccsp-.LPG1(%r13) # setup program check handler + la %r0,0 + lr %r1,%r0 + la %r2,.Lflt0-.LPG1(%r13) + csp %r0,%r2 # Test CSP instruction + oi MACHINE_FLAGS+3-PARMAREA(%r12),8 # set CSP flag +.Lchkcsp: + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 8 -.Lentry:.long 0x04080000,0x80000000 + _stext -.Lpstd: .long .Lpgd+0x7F # segment-table -.Lcr0: .long 0x04b50002 +.Lentry:.long 0x00080000,0x80000000 + _stext +.Lctl: .long 0x04b50002 # cr0: various things + .long 0 # cr1: primary space segment table + .long 0 # cr2: access register translation + .long 0 # cr3: instruction authorization + .long 0 # cr4: instruction authorization + .long 0 # cr5: various things + .long 0 # cr6: I/O interrupts + .long 0 # cr7: secondary space segment table + .long 0 # cr8: access registers translation + .long 0 # cr9: tracing off + .long 0 # cr10: tracing off + .long 0 # cr11: tracing off + .long 0 # cr12: tracing off + .long 0 # cr13: home space segment table + .long 0xc0000000 # cr14: machine check handling off + .long 0 # cr15: linkage stack operations .Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu +.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp .Lflt0: .double 0 .Lparm1:.long PARMAREA .L4malign:.long 0xffc00000 +.Lbigmem:.long 0x04000000 +.Lrdstart:.long 0x02000000 +.Lmaxchunk:.long 0x00ffffff # # params at 10400 (setup.h) @@ -555,17 +591,8 @@ .word 0 # RAMDISK_FLAGS .org COMMAND_LINE -# .byte "root=/dev/nfs rw nfsroot=9.164.160.7:/home/mschwide/nfsboot " -# .byte "ip=9.164.147.12:9.164.160.7:9.164.147.1:255.255.255.0:vmlinux:tr0:off" -# .byte "root=/dev/nfs nfsroot=9.164.160.7:/home/mschwide/nfsboot " -# .byte "ip=9.164.181.228:9.164.160.7:9.164.181.1:255.255.224.0:vmlinux:tr0:off" -# .byte "root=/dev/nfs nfsroot=9.164.160.7:/home/pasch/nfsboot " -# .byte "ip=9.164.185.120:9.164.160.7:9.164.181.1:255.255.224.0:vmlinux:tr0:off" -# .byte "mdisk=402:65536:1229,403:131072:2780 root=/dev/mnda ro" -# .byte "root=/dev/nfs rw nfsroot=9.164.160.209:/usr/local/nfsboot " -# .byte "ip=9.164.181.228:9.164.160.209:9.164.181.1:255.255.224.0:vmlinux:tr0:off" .byte "root=/dev/ram0 ro" -# .byte 0 + .byte 0 # # startup-code, running in virtual mode @@ -625,44 +652,4 @@ .Laregs: .long 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 .align 8 .Ldw: .long 0x000a0000,0x00000000 - -# -# tempory segment-table at 0x11000 -# - .org 0x11000 -.Lpgd: .long .Lpt0+0x1f # 00000000-000fffff - .long .Lpt1+0x1f # 00100000-001fffff - .long .Lpt2+0x1f # 00200000-002fffff - .long .Lpt3+0x1f # 00300000-003fffff - .fill 2044,4,0x20 # 00400000-7fffffff - -# -# tempory page-tables at 0x12000-0x15fff -# - .macro mktable from,to - .long \from*0x10000 - .long \from*0x10000+0x1000 - .long \from*0x10000+0x2000 - .long \from*0x10000+0x3000 - .long \from*0x10000+0x4000 - .long \from*0x10000+0x5000 - .long \from*0x10000+0x6000 - .long \from*0x10000+0x7000 - .long \from*0x10000+0x8000 - .long \from*0x10000+0x9000 - .long \from*0x10000+0xa000 - .long \from*0x10000+0xb000 - .long \from*0x10000+0xc000 - .long \from*0x10000+0xd000 - .long \from*0x10000+0xe000 - .long \from*0x10000+0xf000 - .if \to-\from - mktable "(\from+1)",\to - .endif - .endm - -.Lpt0: mktable 0,15 -.Lpt1: mktable 16,31 -.Lpt2: mktable 32,47 -.Lpt3: mktable 48,63 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/irq.c linux.ac/arch/s390/kernel/irq.c --- linux-2.4.0/arch/s390/kernel/irq.c Sat Aug 5 00:15:37 2000 +++ linux.ac/arch/s390/kernel/irq.c Fri Jan 5 00:00:32 2001 @@ -11,7 +11,6 @@ * S/390 I/O interrupt processing and I/O request processing is * implemented in arch/s390/kernel/s390io.c */ -#include #include #include #include @@ -24,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -205,6 +204,8 @@ if (!local_bh_count(cpu) && atomic_read(&global_bh_count)) continue; + /* this works even though global_irq_lock not + a long, but is arch-specific --RR */ if (!test_and_set_bit(0,&global_irq_lock)) break; } @@ -243,6 +244,8 @@ static inline void get_irqlock(int cpu) { + /* this works even though global_irq_lock not a long, but is + arch-specific --RR */ if (test_and_set_bit(0,&global_irq_lock)) { /* do we already hold the lock? */ if ( cpu == atomic_read(&global_irq_holder)) @@ -398,7 +401,7 @@ void __init init_IRQ(void) { - s390_init_IRQ(); + s390_init_IRQ(); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/mathemu.c linux.ac/arch/s390/kernel/mathemu.c --- linux-2.4.0/arch/s390/kernel/mathemu.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/mathemu.c Fri Jan 5 00:00:32 2001 @@ -9,14 +9,68 @@ * that does not have the IEEE fpu */ +#include #include #include #include #include #include +#include -static void set_CC_df(__u64 val1,__u64 val2) { +#ifdef CONFIG_SYSCTL +int sysctl_ieee_emulation_warnings=1; +#endif + +#define mathemu_put_user(x, ptr) \ +{ \ + if(put_user((x),(ptr))) \ + return 1; \ +} + +#define mathemu_get_user(x, ptr) \ +{ \ + if(get_user((x),(ptr))) \ + return 1; \ +} + + +#define mathemu_copy_from_user(to,from,n) \ +{ \ + if(copy_from_user((to),(from),(n))==-EFAULT) \ + return 1; \ +} + + +#define mathemu_copy_to_user(to, from, n) \ +{ \ + if(copy_to_user((to),(from),(n))==-EFAULT) \ + return 1; \ +} + + + +static void display_emulation_not_implemented(char *instr) +{ + struct pt_regs *regs; + __u16 *location; + +#if CONFIG_SYSCTL + if(sysctl_ieee_emulation_warnings) +#endif + { + regs=current->thread.regs; + location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); + printk("%s ieee fpu instruction not emulated process name: %s pid: %d \n", + instr, + current->comm, current->pid); + printk("%s's PSW: %08lx %08lx\n",instr, + (unsigned long) regs->psw.mask, + (unsigned long) location); + } +} + +static int set_CC_df(__u64 val1,__u64 val2) { int rc; rc = __cmpdf2(val1,val2); current->thread.regs->psw.mask &= 0xFFFFCFFF; @@ -28,9 +82,10 @@ current->thread.regs->psw.mask |= 0x00002000; break; } + return 0; } -static void set_CC_sf(__u32 val1,__u32 val2) { +static int set_CC_sf(__u32 val1,__u32 val2) { int rc; rc = __cmpsf2(val1,val2); current->thread.regs->psw.mask &= 0xFFFFCFFF; @@ -42,384 +97,473 @@ current->thread.regs->psw.mask |= 0x00002000; break; } + return 0; } -static void emu_adb (int rx, __u64 val) { +static int emu_adb (int rx, __u64 val) { current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,val); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_adbr (int rx, int ry) { +static int emu_adbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d, current->thread.fp_regs.fprs[ry].d); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_aeb (int rx, __u32 val) { +static int emu_aeb (int rx, __u32 val) { current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,val); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_aebr (int rx, int ry) { +static int emu_aebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f, current->thread.fp_regs.fprs[ry].f); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_axbr (int rx, int ry) { - printk("axbr emulation not implemented!\n"); +static int emu_axbr (int rx, int ry) { + display_emulation_not_implemented("axbr"); + return 0; } -static void emu_cdb (int rx, __u64 val) { +static int emu_cdb (int rx, __u64 val) { set_CC_df(current->thread.fp_regs.fprs[rx].d,val); + return 0; } -static void emu_cdbr (int rx, int ry) { +static int emu_cdbr (int rx, int ry) { set_CC_df(current->thread.fp_regs.fprs[rx].d,current->thread.fp_regs.fprs[ry].d); + return 0; } -static void emu_cdfbr (int rx, int ry) { +static int emu_cdfbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __floatsidf(current->thread.regs->gprs[ry]); + return 0; } -static void emu_ceb (int rx, __u32 val) { +static int emu_ceb (int rx, __u32 val) { set_CC_sf(current->thread.fp_regs.fprs[rx].f,val); + return 0; } -static void emu_cebr (int rx, int ry) { +static int emu_cebr (int rx, int ry) { set_CC_sf(current->thread.fp_regs.fprs[rx].f,current->thread.fp_regs.fprs[ry].f); + return 0; } -static void emu_cefbr (int rx, int ry) { +static int emu_cefbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __floatsisf(current->thread.regs->gprs[ry]); + return 0; } -static void emu_cfdbr (int rx, int ry, int mask) { +static int emu_cfdbr (int rx, int ry, int mask) { current->thread.regs->gprs[rx] = __fixdfsi(current->thread.fp_regs.fprs[ry].d); + return 0; } -static void emu_cfebr (int rx, int ry, int mask) { +static int emu_cfebr (int rx, int ry, int mask) { current->thread.regs->gprs[rx] = __fixsfsi(current->thread.fp_regs.fprs[ry].f); + return 0; } -static void emu_cfxbr (int rx, int ry, int mask) { - printk("cfxbr emulation not implemented!\n"); +static int emu_cfxbr (int rx, int ry, int mask) { + display_emulation_not_implemented("cfxbr"); + return 0; } -static void emu_cxbr (int rx, int ry) { - printk("cxbr emulation not implemented!\n"); +static int emu_cxbr (int rx, int ry) { + display_emulation_not_implemented("cxbr"); + return 0; } -static void emu_cxfbr (int rx, int ry) { - printk("cxfbr emulation not implemented!\n"); +static int emu_cxfbr (int rx, int ry) { + display_emulation_not_implemented("cxfbr"); + return 0; } -static void emu_ddb (int rx, __u64 val) { +static int emu_ddb (int rx, __u64 val) { current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,val); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_ddbr (int rx, int ry) { +static int emu_ddbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d, current->thread.fp_regs.fprs[ry].d); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_deb (int rx, __u32 val) { +static int emu_deb (int rx, __u32 val) { current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,val); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_debr (int rx, int ry) { +static int emu_debr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f, current->thread.fp_regs.fprs[ry].f); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_didbr (int rx, int ry, int mask) { - printk("didbr emulation not implemented!\n"); +static int emu_didbr (int rx, int ry, int mask) { + display_emulation_not_implemented("didbr"); + return 0; } -static void emu_diebr (int rx, int ry, int mask) { - printk("diebr emulation not implemented!\n"); +static int emu_diebr (int rx, int ry, int mask) { + display_emulation_not_implemented("diebr"); + return 0; } -static void emu_dxbr (int rx, int ry) { - printk("dxbr emulation not implemented!\n"); +static int emu_dxbr (int rx, int ry) { + display_emulation_not_implemented("dxbr"); + return 0; } -static void emu_efpc (int rx, int ry) { - printk("efpc emulation not implemented!\n"); +static int emu_efpc (int rx, int ry) { + current->thread.regs->gprs[rx]=current->thread.fp_regs.fpc; + return 0; } -static void emu_fidbr (int rx, int ry, int mask) { - printk("fidbr emulation not implemented!\n"); +static int emu_fidbr (int rx, int ry, int mask) { + display_emulation_not_implemented("fidbr"); + return 0; } -static void emu_fiebr (int rx, int ry, int mask) { - printk("fiebr emulation not implemented!\n"); +static int emu_fiebr (int rx, int ry, int mask) { + display_emulation_not_implemented("fiebr"); + return 0; } -static void emu_fixbr (int rx, int ry, int mask) { - printk("fixbr emulation not implemented!\n"); +static int emu_fixbr (int rx, int ry, int mask) { + display_emulation_not_implemented("fixbr"); + return 0; } -static void emu_kdb (int rx, __u64 val) { - printk("kdb emulation not implemented!\n"); +static int emu_kdb (int rx, __u64 val) { + display_emulation_not_implemented("kdb"); + return 0; } -static void emu_kdbr (int rx, int ry) { - printk("kdbr emulation not implemented!\n"); +static int emu_kdbr (int rx, int ry) { + display_emulation_not_implemented("kdbr"); + return 0; } -static void emu_keb (int rx, __u32 val) { - printk("keb emulation not implemented!\n"); +static int emu_keb (int rx, __u32 val) { + display_emulation_not_implemented("keb"); + return 0; } -static void emu_kebr (int rx, int ry) { - printk("kebr emulation not implemented!\n"); +static int emu_kebr (int rx, int ry) { + display_emulation_not_implemented("kebr"); + return 0; } -static void emu_kxbr (int rx, int ry) { - printk("kxbr emulation not implemented!\n"); +static int emu_kxbr (int rx, int ry) { + display_emulation_not_implemented("kxbr"); + return 0; } -static void emu_lcdbr (int rx, int ry) { +static int emu_lcdbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __negdf2(current->thread.fp_regs.fprs[ry].d); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_lcebr (int rx, int ry) { +static int emu_lcebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __negsf2(current->thread.fp_regs.fprs[ry].f); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_lcxbr (int rx, int ry) { - printk("lcxbr emulation not implemented!\n"); +static int emu_lcxbr (int rx, int ry) { + display_emulation_not_implemented("lcxbr"); + return 0; } -static void emu_ldeb (int rx, __u32 val) { +static int emu_ldeb (int rx, __u32 val) { current->thread.fp_regs.fprs[rx].d = __extendsfdf2(val); + return 0; } -static void emu_ldebr (int rx, int ry) { +static int emu_ldebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __extendsfdf2(current->thread.fp_regs.fprs[ry].f); + return 0; } -static void emu_ldxbr (int rx, int ry) { - printk("ldxbr emulation not implemented!\n"); +static int emu_ldxbr (int rx, int ry) { + display_emulation_not_implemented("ldxbr"); + return 0; } -static void emu_ledbr (int rx, int ry) { +static int emu_ledbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __truncdfsf2(current->thread.fp_regs.fprs[ry].d); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_lexbr (int rx, int ry) { - printk("lexbr emulation not implemented!\n"); +static int emu_lexbr (int rx, int ry) { + display_emulation_not_implemented("lexbr"); + return 0; } -static void emu_lndbr (int rx, int ry) { - printk("lndbr emulation not implemented!\n"); +static int emu_lndbr (int rx, int ry) { + display_emulation_not_implemented("lndbr"); + return 0; } -static void emu_lnebr (int rx, int ry) { - printk("lnebr emulation not implemented!\n"); +static int emu_lnebr (int rx, int ry) { + display_emulation_not_implemented("lnebr"); + return 0; } -static void emu_lnxbr (int rx, int ry) { - printk("lnxbr emulation not implemented!\n"); +static int emu_lnxbr (int rx, int ry) { + display_emulation_not_implemented("lnxbr"); + return 0; } -static void emu_lpdbr (int rx, int ry) { +static int emu_lpdbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __absdf2(current->thread.fp_regs.fprs[ry].d); set_CC_df(current->thread.fp_regs.fprs[rx].d,0); + return 0; } -static void emu_lpebr (int rx, int ry) { +static int emu_lpebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __abssf2(current->thread.fp_regs.fprs[ry].f); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_lpxbr (int rx, int ry) { - printk("lpxbr emulation not implemented!\n"); +static int emu_lpxbr (int rx, int ry) { + display_emulation_not_implemented("lpxbr"); + return 0; } -static void emu_ltdbr (int rx, int ry) { +static int emu_ltdbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = current->thread.fp_regs.fprs[ry].d; set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_ltebr (int rx, int ry) { +static int emu_ltebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = current->thread.fp_regs.fprs[ry].f; set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_ltxbr (int rx, int ry) { - printk("ltxbr emulation not implemented!\n"); +static int emu_ltxbr (int rx, int ry) { + display_emulation_not_implemented("ltxbr"); + return 0; } -static void emu_lxdb (int rx, __u64 val) { - printk("lxdb emulation not implemented!\n"); +static int emu_lxdb (int rx, __u64 val) { + display_emulation_not_implemented("lxdb"); + return 0; } -static void emu_lxdbr (int rx, int ry) { - printk("lxdbr emulation not implemented!\n"); +static int emu_lxdbr (int rx, int ry) { + display_emulation_not_implemented("lxdbr"); + return 0; } -static void emu_lxeb (int rx, __u32 val) { - printk("lxeb emulation not implemented!\n"); +static int emu_lxeb (int rx, __u32 val) { + display_emulation_not_implemented("lxeb"); + return 0; } -static void emu_lxebr (int rx, int ry) { - printk("lxebr emulation not implemented!\n"); +static int emu_lxebr (int rx, int ry) { + display_emulation_not_implemented("lxebr"); + return 0; } -static void emu_madb (int rx, __u64 val, int mask) { - printk("madb emulation not implemented!\n"); +static int emu_madb (int rx, __u64 val, int mask) { + display_emulation_not_implemented("madb"); + return 0; } -static void emu_madbr (int rx, int ry, int mask) { - printk(" emulation not implemented!\n"); +static int emu_madbr (int rx, int ry, int mask) { + display_emulation_not_implemented("madbr"); + return 0; } -static void emu_maeb (int rx, __u32 val, int mask) { - printk("maeb emulation not implemented!\n"); +static int emu_maeb (int rx, __u32 val, int mask) { + display_emulation_not_implemented("maeb"); + return 0; } -static void emu_maebr (int rx, int ry, int mask) { - printk("maebr emulation not implemented!\n"); +static int emu_maebr (int rx, int ry, int mask) { + display_emulation_not_implemented("maebr"); + return 0; } -static void emu_mdb (int rx, __u64 val) { +static int emu_mdb (int rx, __u64 val) { current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,val); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_mdbr (int rx, int ry) { +static int emu_mdbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d, current->thread.fp_regs.fprs[ry].d); set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_mdeb (int rx, __u32 val) { - printk("mdeb emulation not implemented!\n"); +static int emu_mdeb (int rx, __u32 val) { + display_emulation_not_implemented("mdeb"); + return 0; } -static void emu_mdebr (int rx, int ry) { - printk("mdebr emulation not implemented!\n"); +static int emu_mdebr (int rx, int ry) { + display_emulation_not_implemented("mdebr"); + return 0; } -static void emu_meeb (int rx, __u32 val) { +static int emu_meeb (int rx, __u32 val) { current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f, val); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_meebr (int rx, int ry) { +static int emu_meebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f, current->thread.fp_regs.fprs[ry].f); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_msdb (int rx, __u64 val, int mask) { - printk("msdb emulation not implemented!\n"); +static int emu_msdb (int rx, __u64 val, int mask) { + display_emulation_not_implemented("msdb"); + return 0; } -static void emu_msdbr (int rx, int ry, int mask) { - printk("msdbr emulation not implemented!\n"); +static int emu_msdbr (int rx, int ry, int mask) { + display_emulation_not_implemented("msdbr"); + return 0; } -static void emu_mseb (int rx, __u32 val, int mask) { - printk("mseb emulation not implemented!\n"); +static int emu_mseb (int rx, __u32 val, int mask) { + display_emulation_not_implemented("mseb"); + return 0; } -static void emu_msebr (int rx, int ry, int mask) { - printk("msebr emulation not implemented!\n"); +static int emu_msebr (int rx, int ry, int mask) { + display_emulation_not_implemented("msebr"); + return 0; } -static void emu_mxbr (int rx, int ry) { - printk("mxbr emulation not implemented!\n"); +static int emu_mxbr (int rx, int ry) { + display_emulation_not_implemented("mxbr"); + return 0; } -static void emu_mxdb (int rx, __u64 val) { - printk("mxdb emulation not implemented!\n"); +static int emu_mxdb (int rx, __u64 val) { + display_emulation_not_implemented("mxdb"); + return 0; } -static void emu_mxdbr (int rx, int ry) { - printk("mxdbr emulation not implemented!\n"); +static int emu_mxdbr (int rx, int ry) { + display_emulation_not_implemented("mxdbr"); + return 0; } -static void emu_sdb (int rx, __u64 val) { +static int emu_sdb (int rx, __u64 val) { current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d, val); set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_sdbr (int rx, int ry) { +static int emu_sdbr (int rx, int ry) { current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d, current->thread.fp_regs.fprs[ry].d); set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL); + return 0; } -static void emu_seb (int rx, __u32 val) { +static int emu_seb (int rx, __u32 val) { current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f, val); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_sebr (int rx, int ry) { +static int emu_sebr (int rx, int ry) { current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f, current->thread.fp_regs.fprs[ry].f); set_CC_sf(current->thread.fp_regs.fprs[rx].f,0); + return 0; } -static void emu_sfpc (int rx, int ry) { - printk("sfpc emulation not implemented!\n"); +static int emu_sfpc (int rx, int ry) { + __u32 val=current->thread.regs->gprs[rx]; + if(val==0) + current->thread.fp_regs.fpc=val; + else + display_emulation_not_implemented("sfpc"); + return 0; } -static void emu_sqdb (int rx, __u64 val) { - printk("sqdb emulation not implemented!\n"); +static int emu_sqdb (int rx, __u64 val) { + display_emulation_not_implemented("sqdb"); + return 0; } -static void emu_sqdbr (int rx, int ry) { - printk("sqdbr emulation not implemented!\n"); +static int emu_sqdbr (int rx, int ry) { + display_emulation_not_implemented("sqdbr"); + return 0; } -static void emu_sqeb (int rx, __u32 val) { - printk("sqeb emulation not implemented!\n"); +static int emu_sqeb (int rx, __u32 val) { + display_emulation_not_implemented("sqeb"); + return 0; } -static void emu_sqebr (int rx, int ry) { - printk("sqebr emulation not implemented!\n"); +static int emu_sqebr (int rx, int ry) { + display_emulation_not_implemented("sqebr"); + return 0; } -static void emu_sqxbr (int rx, int ry) { - printk("sqxbr emulation not implemented!\n"); +static int emu_sqxbr (int rx, int ry) { + display_emulation_not_implemented("sqxbr"); + return 0; } -static void emu_sxbr (int rx, int ry) { - printk("sxbr emulation not implemented!\n"); +static int emu_sxbr (int rx, int ry) { + display_emulation_not_implemented("sxbr"); + return 0; } -static void emu_tcdb (int rx, __u64 val) { - printk("tcdb emulation not implemented!\n"); +static int emu_tcdb (int rx, __u64 val) { + display_emulation_not_implemented("tcdb"); + return 0; } -static void emu_tceb (int rx, __u32 val) { - printk("tceb emulation not implemented!\n"); +static int emu_tceb (int rx, __u32 val) { + display_emulation_not_implemented("tceb"); + return 0; } -static void emu_tcxb (int rx, __u64 val) { - printk("tcxb emulation not implemented!\n"); +static int emu_tcxb (int rx, __u64 val) { + display_emulation_not_implemented("tcxb"); + return 0; } @@ -473,6 +617,7 @@ } int math_emu_b3(__u8 *opcode, struct pt_regs * regs) { + int rc=0; static const __u8 format_table[] = { 2, 2, 2, 2, 9, 1, 2, 1, 2, 2, 2, 2, 9, 2, 4, 4, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3, @@ -538,84 +683,82 @@ emu_store_regd((opcode[3]>>4)&15); emu_store_regd(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); - emu_load_regd((opcode[3]>>4)&15); - emu_load_regd(opcode[3]&15); - return 0; + emu_load_regd((opcode[3]>>4)&15); + emu_load_regd(opcode[3]&15); + return rc; case 2: /* RRE format, float operation */ emu_store_rege((opcode[3]>>4)&15); emu_store_rege(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); - emu_load_rege((opcode[3]>>4)&15); - emu_load_rege(opcode[3]&15); - return 0; + emu_load_rege((opcode[3]>>4)&15); + emu_load_rege(opcode[3]&15); + return rc; case 3: /* RRF format, double operation */ emu_store_regd((opcode[3]>>4)&15); emu_store_regd(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); - emu_load_regd((opcode[3]>>4)&15); - emu_load_regd(opcode[3]&15); - return 0; + emu_load_regd((opcode[3]>>4)&15); + emu_load_regd(opcode[3]&15); + return rc; case 4: /* RRF format, float operation */ emu_store_rege((opcode[3]>>4)&15); emu_store_rege(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); - emu_load_rege((opcode[3]>>4)&15); - emu_load_rege(opcode[3]&15); - return 0; + emu_load_rege((opcode[3]>>4)&15); + emu_load_rege(opcode[3]&15); + return rc; case 5: /* RRE format, cefbr instruction */ emu_store_rege((opcode[3]>>4)&15); /* call the emulation function */ - ((void (*)(int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); - emu_load_rege((opcode[3]>>4)&15); - return 0; + emu_load_rege((opcode[3]>>4)&15); + return rc; case 6: /* RRE format, cdfbr & cxfbr instruction */ emu_store_regd((opcode[3]>>4)&15); /* call the emulation function */ - ((void (*)(int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); - emu_load_regd((opcode[3]>>4)&15); - return 0; - /* FIXME !! */ - return 0; - case 7: /* RRF format, cfebr instruction */ + emu_load_regd((opcode[3]>>4)&15); + return rc; + case 7: /* RRF format, cfebr instruction */ emu_store_rege(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); - return 0; + return rc; case 8: /* RRF format, cfdbr & cfxbr instruction */ emu_store_regd(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15,opcode[2]>>4); - return 0; + return rc; case 9: /* RRE format, ldebr & mdebr instruction */ /* float store but double load */ emu_store_rege((opcode[3]>>4)&15); emu_store_rege(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); - emu_load_regd((opcode[3]>>4)&15); - return 0; + emu_load_regd((opcode[3]>>4)&15); + return rc; case 10: /* RRE format, ledbr instruction */ /* double store but float load */ emu_store_regd((opcode[3]>>4)&15); emu_store_regd(opcode[3]&15); /* call the emulation function */ - ((void (*)(int, int))jump_table[opcode[1]]) + rc=((int (*)(int, int))jump_table[opcode[1]]) (opcode[3]>>4,opcode[3]&15); - emu_load_rege((opcode[3]>>4)&15); - return 0; + emu_load_rege((opcode[3]>>4)&15); + return rc; default: return 1; } @@ -632,6 +775,8 @@ } int math_emu_ed(__u8 *opcode, struct pt_regs * regs) { + int rc=0; + static const __u8 format_table[] = { 0, 0, 0, 0, 5, 1, 2, 1, 2, 2, 2, 2, 5, 2, 4, 4, 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 1, 3, 3, @@ -669,13 +814,12 @@ emu_store_regd((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if copy_from_user fails ? */ - copy_from_user(&temp, dxb, 8); + mathemu_copy_from_user(&temp, dxb, 8); /* call the emulation function */ - ((void (*)(int, __u64))jump_table[opcode[5]]) + rc=((int (*)(int, __u64))jump_table[opcode[5]]) (opcode[1]>>4,temp); - emu_load_regd((opcode[1]>>4)&15); - return 0; + emu_load_regd((opcode[1]>>4)&15); + return rc; } case 2: /* RXE format, __u32 constant */ { __u32 *dxb, temp; @@ -684,13 +828,12 @@ emu_store_rege((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if get_user fails ? */ - get_user(temp, dxb); + mathemu_get_user(temp, dxb); /* call the emulation function */ - ((void (*)(int, __u32))jump_table[opcode[5]]) + rc=((int (*)(int, __u32))jump_table[opcode[5]]) (opcode[1]>>4,temp); - emu_load_rege((opcode[1]>>4)&15); - return 0; + emu_load_rege((opcode[1]>>4)&15); + return rc; } case 3: /* RXF format, __u64 constant */ { __u32 *dxb, temp; @@ -699,13 +842,12 @@ emu_store_regd((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if copy_from_user fails ? */ - copy_from_user(&temp, dxb, 8); + mathemu_copy_from_user(&temp, dxb, 8); /* call the emulation function */ - ((void (*)(int, __u32, int))jump_table[opcode[5]]) + rc=((int (*)(int, __u32, int))jump_table[opcode[5]]) (opcode[1]>>4,temp,opcode[4]>>4); - emu_load_regd((opcode[1]>>4)&15); - return 0; + emu_load_regd((opcode[1]>>4)&15); + return rc; } case 4: /* RXF format, __u32 constant */ { __u32 *dxb, temp; @@ -714,29 +856,27 @@ emu_store_rege((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if get_user fails ? */ - get_user(temp, dxb); + mathemu_get_user(temp, dxb); /* call the emulation function */ - ((void (*)(int, __u32, int))jump_table[opcode[5]]) + rc=((int (*)(int, __u32, int))jump_table[opcode[5]]) (opcode[1]>>4,temp,opcode[4]>>4); emu_load_rege((opcode[1]>>4)&15); - return 0; + return rc; } case 5: /* RXE format, __u32 constant */ /* store_rege and load_regd */ - { + { __u32 *dxb, temp; __u32 opc; emu_store_rege((opcode[1]>>4)&15); opc = *((__u32 *) opcode); dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if get_user fails ? */ - get_user(temp, dxb); + mathemu_get_user(temp, dxb); /* call the emulation function */ - ((void (*)(int, __u32))jump_table[opcode[5]]) + rc=((int (*)(int, __u32))jump_table[opcode[5]]) (opcode[1]>>4,temp); emu_load_regd((opcode[1]>>4)&15); - return 0; + return rc; } default: return 1; @@ -746,7 +886,7 @@ /* * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6} */ -void math_emu_ldr(__u8 *opcode) { +int math_emu_ldr(__u8 *opcode) { __u16 opc = *((__u16 *) opcode); if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */ @@ -772,12 +912,13 @@ current->thread.fp_regs.fprs[(opc&0x00f0)>>4] = current->thread.fp_regs.fprs[opc&0x000f]; } + return 0; } /* * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6} */ -void math_emu_ler(__u8 *opcode) { +int math_emu_ler(__u8 *opcode) { __u16 opc = *((__u16 *) opcode); if ((opc & 0x0090) == 0) { /* test if rx in {0,2,4,6} */ @@ -803,61 +944,68 @@ current->thread.fp_regs.fprs[(opc&0x00f0)>>4] = current->thread.fp_regs.fprs[opc&0x000f]; } + return 0; } /* * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6} */ -void math_emu_ld(__u8 *opcode, struct pt_regs * regs) { +int math_emu_ld(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u64 *dxb; dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if copy_from_user fails ? */ - copy_from_user(¤t->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8); + mathemu_copy_from_user(¤t->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8); + return 0; } /* * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6} */ -void math_emu_le(__u8 *opcode, struct pt_regs * regs) { +int math_emu_le(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u32 *mem, *dxb; dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if get_user fails ? */ mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f); - get_user(mem[0], dxb); + mathemu_get_user(mem[0], dxb); + return 0; } /* * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6} */ -void math_emu_std(__u8 *opcode, struct pt_regs * regs) { +int math_emu_std(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u64 *dxb; dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if copy_to_user fails ? */ - copy_to_user(dxb, ¤t->thread.fp_regs.fprs[(opc>>20)&15].d, 8); + mathemu_copy_to_user(dxb, ¤t->thread.fp_regs.fprs[(opc>>20)&15].d, 8); + return 0; } /* * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6} */ -void math_emu_ste(__u8 *opcode, struct pt_regs * regs) { +int math_emu_ste(__u8 *opcode, struct pt_regs * regs) { __u32 opc = *((__u32 *) opcode); __u32 *mem, *dxb; dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc); - /* FIXME: how to react if put_user fails ? */ + /* FIXME: how to react if mathemu_put_user fails ? */ mem = (__u32 *) (¤t->thread.fp_regs.fprs[(opc>>20)&15].f); - put_user(mem[0], dxb); + mathemu_put_user(mem[0], dxb); + return 0; } /* * Emulate LFPC D(B) */ int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) { - /* FIXME: how to do that ?!? */ + __u32 *dxb,temp; + __u32 opc = *((__u32 *) opcode); + dxb= (__u32 *) calc_addr(regs,0,opc>>12,opc); + mathemu_get_user(temp, dxb); + if(temp!=0) + display_emulation_not_implemented("lfpc"); return 0; } @@ -865,7 +1013,10 @@ * Emulate STFPC D(B) */ int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) { - /* FIXME: how to do that ?!? */ + __u32 *dxb; + __u32 opc = *((__u32 *) opcode); + dxb= (__u32 *) calc_addr(regs,0,opc>>12,opc); + mathemu_put_user(current->thread.fp_regs.fpc, dxb); return 0; } @@ -874,6 +1025,7 @@ */ int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) { /* FIXME: how to do that ?!? */ + display_emulation_not_implemented("srnm"); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/process.c linux.ac/arch/s390/kernel/process.c --- linux-2.4.0/arch/s390/kernel/process.c Tue Sep 5 21:50:01 2000 +++ linux.ac/arch/s390/kernel/process.c Fri Jan 5 00:00:32 2001 @@ -33,7 +33,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -67,7 +70,9 @@ if (softirq_active(smp_processor_id()) & softirq_mask(smp_processor_id())) { do_softirq(); - continue; + __sti(); + if (!current->need_resched) + continue; } if (current->need_resched) { schedule(); @@ -92,12 +97,13 @@ 0 returned you know you've got all the lines */ -int sprintf_regs(int line, char *buff, struct task_struct * task, - struct thread_struct *thread, struct pt_regs * regs) -{ +static int sprintf_regs(int line, char *buff, struct task_struct *task, struct pt_regs *regs) +{ int linelen=0; int regno,chaincnt; u32 backchain,prev_backchain,endchain; + u32 ksp = 0; + char *mode = "???"; enum { @@ -118,106 +124,125 @@ sp_kern_backchain1 }; - if(task) - thread = &task->thread; - if(thread) - regs = thread->regs; - switch (line) { - case sp_linefeed: + if (task) + ksp = task->thread.ksp; + if (regs && !(regs->psw.mask & PSW_PROBLEM_STATE)) + ksp = regs->gprs[15]; + + if (regs) + mode = (regs->psw.mask & PSW_PROBLEM_STATE)? + "User" : "Kernel"; + + switch(line) + { + case sp_linefeed: linelen=sprintf(buff,"\n"); break; case sp_psw: if(regs) - linelen = sprintf(buff,"User PSW: %08lx %08lx\n", - (unsigned long) regs->psw.mask, - (unsigned long) regs->psw.addr); + linelen=sprintf(buff, "%s PSW: %08lx %08lx\n", mode, + (unsigned long) regs->psw.mask, + (unsigned long) regs->psw.addr); else - linelen = sprintf(buff,"pt_regs=NULL some info unavailable\n"); + linelen=sprintf(buff,"pt_regs=NULL some info unavailable\n"); break; case sp_ksp: - if (task) - linelen += sprintf(&buff[linelen], - "task: %08x ", (addr_t)task); - if (thread) - linelen += sprintf(&buff[linelen], - "thread: %08x ksp: %08x ", - (addr_t)thread,(addr_t)thread->ksp); - if (regs) - linelen += sprintf(&buff[linelen], - "pt_regs: %08x\n", (addr_t)regs); + linelen=sprintf(&buff[linelen], + "task: %08x ksp: %08x pt_regs: %08x\n", + (addr_t)task, (addr_t)ksp, (addr_t)regs); break; case sp_gprs: - if (regs) - linelen = sprintf(buff,"User GPRS:\n"); + if(regs) + linelen=sprintf(buff, "%s GPRS:\n", mode); break; case sp_gprs1 ... sp_gprs4: - if (regs) { - regno = (line-sp_gprs1)*4; - linelen = sprintf(buff,"%08x %08x %08x %08x\n", - regs->gprs[regno], - regs->gprs[regno+1], - regs->gprs[regno+2], - regs->gprs[regno+3]); + if(regs) + { + regno=(line-sp_gprs1)*4; + linelen=sprintf(buff,"%08x %08x %08x %08x\n", + regs->gprs[regno], + regs->gprs[regno+1], + regs->gprs[regno+2], + regs->gprs[regno+3]); } break; case sp_acrs: - if (regs) - linelen = sprintf(buff,"User ACRS:\n"); + if(regs) + linelen=sprintf(buff, "%s ACRS:\n", mode); break; case sp_acrs1 ... sp_acrs4: - if (regs) { - regno = (line-sp_acrs1)*4; - linelen = sprintf(buff,"%08x %08x %08x %08x\n", - regs->acrs[regno], - regs->acrs[regno+1], - regs->acrs[regno+2], - regs->acrs[regno+3]); + if(regs) + { + regno=(line-sp_acrs1)*4; + linelen=sprintf(buff,"%08x %08x %08x %08x\n", + regs->acrs[regno], + regs->acrs[regno+1], + regs->acrs[regno+2], + regs->acrs[regno+3]); } break; case sp_kern_backchain: - if (thread && thread->ksp && regs) - linelen = sprintf(buff,"Kernel BackChain CallChain BackChain CallChain\n"); + if (regs && (regs->psw.mask & PSW_PROBLEM_STATE)) + break; + if (ksp) + linelen=sprintf(buff, "Kernel BackChain CallChain\n"); break; default: - if(thread && thread->ksp && regs) { - backchain = (thread->ksp & PSW_ADDR_MASK); - endchain = ((backchain & (-8192)) + 8192); - prev_backchain = backchain - 1; - line -= sp_kern_backchain1; - for (chaincnt = 0; ; chaincnt++) { - if ((backchain == 0) || - (backchain >= endchain) || - (chaincnt >= 8) || - (prev_backchain >= backchain)) + if (ksp) + { + + backchain=ksp&PSW_ADDR_MASK; + endchain=((backchain&(-8192))+8192); + prev_backchain=backchain-1; + line-=sp_kern_backchain1; + for(chaincnt=0;;chaincnt++) + { + if((backchain==0)||(backchain>=endchain) + ||(chaincnt>=8)||(prev_backchain>=backchain)) break; - if ((chaincnt >> 1) == line) { - linelen += sprintf(&buff[linelen],"%s%08x %08x ", - (chaincnt&1) ? "":" ", - backchain,*(u32 *)(backchain+56)); - } - if ((chaincnt >> 1) > line) + if(chaincnt==line) + { + linelen+=sprintf(&buff[linelen]," %08x [<%08lx>]\n", + backchain, + *(u32 *)(backchain+56)&PSW_ADDR_MASK); break; - prev_backchain = backchain; - backchain = (*((u32 *)backchain)) & PSW_ADDR_MASK; + } + prev_backchain=backchain; + backchain=(*((u32 *)backchain))&PSW_ADDR_MASK; } - if (linelen) - linelen += sprintf(&buff[linelen],"\n"); } } - return linelen; + return(linelen); } -void show_regs(struct task_struct *task, struct thread_struct *thread, - struct pt_regs *regs) +void show_regs(struct pt_regs *regs) { char buff[80]; int line; + + printk("CPU: %d\n",smp_processor_id()); + printk("Process %s (pid: %d, stackpage=%08X)\n", + current->comm, current->pid, 4096+(addr_t)current); - for (line = 0; sprintf_regs(line,buff,task,thread,regs); line++) + for (line = 0; sprintf_regs(line, buff, current, regs); line++) printk(buff); } +char *task_show_regs(struct task_struct *task, char *buffer) +{ + int line, len; + + for (line = 0; ; line++) + { + len = sprintf_regs(line, buffer, task, task->thread.regs); + if (!len) break; + buffer += len; + } + return buffer; +} + + int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { int clone_arg = flags | CLONE_VM; @@ -327,7 +352,7 @@ lock_kernel(); clone_flags = regs.gprs[3]; - newsp = regs.gprs[2]; + newsp = regs.orig_gpr2; if (!newsp) newsp = regs.gprs[15]; ret = do_fork(clone_flags, newsp, ®s, 0); @@ -365,7 +390,19 @@ goto out; error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], ®s); if (error == 0) - current->flags &= ~PF_DTRACE; + { + current->ptrace &= ~PT_DTRACE; + current->thread.fp_regs.fpc=0; + if(MACHINE_HAS_IEEE) + { + __asm__ __volatile__ + ("sr 0,0\n\t" + "sfpc 0,0\n\t" + : + : + :"0"); + } + } putname(filename); out: return error; @@ -412,21 +449,77 @@ unsigned long get_wchan(struct task_struct *p) { - unsigned long r14, r15; + unsigned long r14, r15, bc; unsigned long stack_page; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; stack_page = (unsigned long) p; r15 = p->thread.ksp; + if (!stack_page || r15 < stack_page || r15 >= 8188+stack_page) + return 0; + bc = (*(unsigned long *) r15) & 0x7fffffff; do { - r14 = *(unsigned long *) (r15+56); + if (bc < stack_page || bc >= 8188+stack_page) + return 0; + r14 = (*(unsigned long *) (bc+56)) & 0x7fffffff; if (r14 < first_sched || r14 >= last_sched) return r14; - r15 = *(unsigned long *) (r15+60); + bc = (*(unsigned long *) bc) & 0x7fffffff; } while (count++ < 16); return 0; } #undef last_sched #undef first_sched +/* + * This should be safe even if called from tq_scheduler + * A typical mask would be sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM) or 0. + * + */ +void s390_daemonize(char *name,unsigned long mask,int use_init_fs) +{ + struct fs_struct *fs; + extern struct task_struct *child_reaper; + struct task_struct *this_process=current; + + /* + * If we were started as result of loading a module, close all of the + * user space pages. We don't need them, and if we didn't close them + * they would be locked into memory. + */ + exit_mm(current); + + this_process->session = 1; + this_process->pgrp = 1; + if(name) + { + strncpy(current->comm,name,15); + current->comm[15]=0; + } + else + current->comm[0]=0; + /* set signal mask to what we want to respond */ + siginitsetinv(¤t->blocked,mask); + /* exit_signal isn't set up */ + /* if we inherit from cpu idle */ + this_process->exit_signal=SIGCHLD; + /* if priority=0 schedule can go into a tight loop */ + this_process->policy= SCHED_OTHER; + /* nice goes priority=20-nice; */ + this_process->nice=10; + if(use_init_fs) + { + exit_fs(this_process); /* current->fs->count--; */ + fs = init_task.fs; + current->fs = fs; + atomic_inc(&fs->count); + exit_files(current); + } + write_lock_irq(&tasklist_lock); + /* We want init as our parent */ + REMOVE_LINKS(this_process); + this_process->p_opptr=this_process->p_pptr=child_reaper; + SET_LINKS(this_process); + write_unlock_irq(&tasklist_lock); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/ptrace.c linux.ac/arch/s390/kernel/ptrace.c --- linux-2.4.0/arch/s390/kernel/ptrace.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/ptrace.c Fri Jan 5 00:00:32 2001 @@ -66,10 +66,16 @@ regs->psw.mask |=PSW_PER_MASK; else regs->psw.mask &= ~PSW_PER_MASK; - if(per_info->control_regs.bits.storage_alt_space_ctl) - task->thread.user_seg|=USER_STD_MASK; + if (per_info->control_regs.bits.em_storage_alteration) + { + per_info->control_regs.bits.storage_alt_space_ctl=1; + //((pgd_t *)__pa(task->mm->pgd))->pgd |= USER_STD_MASK; + } else - task->thread.user_seg&=~USER_STD_MASK; + { + per_info->control_regs.bits.storage_alt_space_ctl=0; + //((pgd_t *)__pa(task->mm->pgd))->pgd &= ~USER_STD_MASK; + } } void set_single_step(struct task_struct *task) @@ -209,10 +215,10 @@ if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) goto out; /* set the ptrace bit in the process flags. */ - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; ret = 0; goto out; } @@ -237,9 +243,9 @@ (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE)) goto out; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); if (child->p_pptr != current) @@ -256,16 +262,20 @@ } ret = -ESRCH; // printk("child=%lX child->flags=%lX",child,child->flags); - if (!(child->flags & PF_PTRACED)) - goto out; - if (child->state != TASK_STOPPED) + /* I added child!=current line so we can get the */ + /* ieee_instruction_pointer from the user structure DJB */ + if(child!=current) { - if (request != PTRACE_KILL) + if (!(child->ptrace & PT_PTRACED)) + goto out; + if (child->state != TASK_STOPPED) + { + if (request != PTRACE_KILL) + goto out; + } + if (child->p_pptr != current) goto out; } - if (child->p_pptr != current) - goto out; - switch (request) { /* If I and D space are separate, these will need to be fixed. */ @@ -303,9 +313,9 @@ if ((unsigned long) data >= _NSIG) break; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; /* make sure the single step bit is not set. */ clear_single_step(child); @@ -332,7 +342,7 @@ ret = -EIO; if ((unsigned long) data >= _NSIG) break; - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; set_single_step(child); /* give it a chance to run. */ @@ -344,7 +354,7 @@ ret = -EIO; if ((unsigned long) data >= _NSIG) break; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); @@ -374,11 +384,11 @@ asmlinkage void syscall_trace(void) { lock_kernel(); - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) - != (PF_PTRACED|PF_TRACESYS)) + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) + != (PT_PTRACED|PT_TRACESYS)) goto out; current->exit_code = SIGTRAP; - current->state = TASK_STOPPED; + set_current_state(TASK_STOPPED); notify_parent(current, SIGCHLD); schedule(); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/reipl.S linux.ac/arch/s390/kernel/reipl.S --- linux-2.4.0/arch/s390/kernel/reipl.S Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/reipl.S Fri Jan 5 00:00:32 2001 @@ -1,4 +1,13 @@ +/* + * arch/s390/kernel/reipl.S + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com) + */ + #include + .globl do_reipl do_reipl: basr %r13,0 .Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) @@ -7,7 +16,7 @@ ni .Lctlsave-.Lpg0(%r13),0xef lctl %c0,%c0,.Lctlsave-.Lpg0(%r13) lr %r1,%r2 - mvc __LC_PGM_NEW_PSW(8,0),.Lpcnew-.Lpg0(%r13) + mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13) stsch .Lschib-.Lpg0(%r13) oi .Lschib+5-.Lpg0(%r13),0x84 .Lecs: xi .Lschib+27-.Lpg0(%r13),0x01 @@ -15,9 +24,9 @@ ssch .Liplorb-.Lpg0(%r13) jz .L001 bas %r14,.Ldisab-.Lpg0(%r13) -.L001: mvc __LC_IO_NEW_PSW(8,0),.Lionew-.Lpg0(%r13) +.L001: mvc __LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13) .Ltpi: lpsw .Lwaitpsw-.Lpg0(%r13) -.Lcont: c %r1,__LC_SUBCHANNEL_ID(%r0) +.Lcont: c %r1,__LC_SUBCHANNEL_ID jnz .Ltpi clc __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13) jnz .Ltpi @@ -29,7 +38,7 @@ jz .L003 bas %r14,.Ldisab-.Lpg0(%r13) .L003: spx .Lnull-.Lpg0(%r13) - st %r1,__LC_SUBCHANNEL_ID(%r0) + st %r1,__LC_SUBCHANNEL_ID lpsw 0 sigp 0,0,0(6) .Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/s390_ext.c linux.ac/arch/s390/kernel/s390_ext.c --- linux-2.4.0/arch/s390/kernel/s390_ext.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/s390/kernel/s390_ext.c Fri Jan 5 00:00:32 2001 @@ -0,0 +1,77 @@ +/* + * arch/s390/kernel/s390_ext.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com) + */ + +#include +#include +#include +#include + +/* + * Simple hash strategy: index = code & 0xff; + * ext_int_hash[index] is the start of the list for all external interrupts + * that hash to this index. With the current set of external interrupts + * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console and 0x4000 + * iucv) this is always the first element. + */ +ext_int_info_t *ext_int_hash[256] = { 0, }; +ext_int_info_t ext_int_info_timer; +ext_int_info_t ext_int_info_hwc; + +int register_external_interrupt(__u16 code, ext_int_handler_t handler) { + ext_int_info_t *p; + int index; + + index = code & 0xff; + p = ext_int_hash[index]; + while (p != NULL) { + if (p->code == code) + return -EBUSY; + p = p->next; + } + if (code == 0x1004) /* time_init is done before kmalloc works :-/ */ + p = &ext_int_info_timer; + else if (code == 0x2401) /* hwc_init is done too early too */ + p = &ext_int_info_hwc; + else + p = (ext_int_info_t *) + kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC); + if (p == NULL) + return -ENOMEM; + p->code = code; + p->handler = handler; + p->next = ext_int_hash[index]; + ext_int_hash[index] = p; + return 0; +} + +int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) { + ext_int_info_t *p, *q; + int index; + + index = code & 0xff; + q = NULL; + p = ext_int_hash[index]; + while (p != NULL) { + if (p->code == code && p->handler == handler) + break; + q = p; + p = p->next; + } + if (p == NULL) + return -ENOENT; + if (q != NULL) + q->next = p->next; + else + ext_int_hash[index] = p->next; + if (code != 0x1004 && code != 0x2401) + kfree(p); + return 0; +} + + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/s390_ksyms.c linux.ac/arch/s390/kernel/s390_ksyms.c --- linux-2.4.0/arch/s390/kernel/s390_ksyms.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/s390_ksyms.c Fri Jan 5 00:00:32 2001 @@ -5,14 +5,27 @@ */ #include #include +#include +#include +#include #include -#include +#include +#include +#include #include +#include +#if CONFIG_CHANDEV +#include +#endif +#if CONFIG_IP_MULTICAST +#include +#endif /* * I/O subsystem */ EXPORT_SYMBOL(halt_IO); +EXPORT_SYMBOL(clear_IO); EXPORT_SYMBOL(do_IO); EXPORT_SYMBOL(resume_IO); EXPORT_SYMBOL(ioinfo); @@ -22,6 +35,35 @@ EXPORT_SYMBOL(get_devno_by_irq); EXPORT_SYMBOL(get_irq_first); EXPORT_SYMBOL(get_irq_next); +EXPORT_SYMBOL(read_conf_data); +EXPORT_SYMBOL(read_dev_chars); +EXPORT_SYMBOL(s390_request_irq_special); +EXPORT_SYMBOL(s390_device_register); +EXPORT_SYMBOL(s390_device_unregister); + +EXPORT_SYMBOL(ccw_alloc_request); +EXPORT_SYMBOL(ccw_free_request); + +EXPORT_SYMBOL(register_external_interrupt); +EXPORT_SYMBOL(unregister_external_interrupt); + +/* + * debug feature + */ +EXPORT_SYMBOL(debug_register); +EXPORT_SYMBOL(debug_unregister); +EXPORT_SYMBOL(debug_set_level); +EXPORT_SYMBOL(debug_register_view); +EXPORT_SYMBOL(debug_unregister_view); +EXPORT_SYMBOL(debug_event); +EXPORT_SYMBOL(debug_int_event); +EXPORT_SYMBOL(debug_text_event); +EXPORT_SYMBOL(debug_exception); +EXPORT_SYMBOL(debug_int_exception); +EXPORT_SYMBOL(debug_text_exception); +EXPORT_SYMBOL(debug_hex_ascii_view); +EXPORT_SYMBOL(debug_raw_view); +EXPORT_SYMBOL(debug_dflt_header_fn); /* * memory management @@ -29,6 +71,16 @@ EXPORT_SYMBOL(_oi_bitmap); EXPORT_SYMBOL(_ni_bitmap); EXPORT_SYMBOL(_zb_findmap); +EXPORT_SYMBOL(__copy_from_user_fixup); +EXPORT_SYMBOL(__copy_to_user_fixup); + +/* + * semaphore ops + */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); /* * string functions @@ -36,6 +88,7 @@ EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL_NOVERS(strlen); EXPORT_SYMBOL_NOVERS(strchr); EXPORT_SYMBOL_NOVERS(strcmp); EXPORT_SYMBOL_NOVERS(strncat); @@ -46,19 +99,42 @@ EXPORT_SYMBOL_NOVERS(strtok); EXPORT_SYMBOL_NOVERS(strpbrk); +EXPORT_SYMBOL_NOVERS(_ascebc_500); +EXPORT_SYMBOL_NOVERS(_ebcasc_500); +EXPORT_SYMBOL_NOVERS(_ascebc); +EXPORT_SYMBOL_NOVERS(_ebcasc); +EXPORT_SYMBOL_NOVERS(_ebc_tolower); +EXPORT_SYMBOL_NOVERS(_ebc_toupper); + /* * misc. */ +EXPORT_SYMBOL(module_list); +EXPORT_SYMBOL(__udelay); #ifdef CONFIG_SMP #include EXPORT_SYMBOL(__global_cli); EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_save_flags); EXPORT_SYMBOL(__global_restore_flags); +EXPORT_SYMBOL(lowcore_ptr); EXPORT_SYMBOL(global_bh_lock); EXPORT_SYMBOL(kernel_flag); +EXPORT_SYMBOL(smp_ctl_set_bit); +EXPORT_SYMBOL(smp_ctl_clear_bit); #endif EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(csum_fold); - +#if CONFIG_CHANDEV +EXPORT_SYMBOL(chandev_register_and_probe); +EXPORT_SYMBOL(chandev_request_irq); +EXPORT_SYMBOL(chandev_unregister); +EXPORT_SYMBOL(chandev_initdevice); +EXPORT_SYMBOL(chandev_initnetdevice); +#endif +#if CONFIG_IP_MULTICAST +/* Required for lcs gigabit ethernet multicast support */ +EXPORT_SYMBOL(arp_mc_map); +#endif +EXPORT_SYMBOL(s390_daemonize); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/s390dyn.c linux.ac/arch/s390/kernel/s390dyn.c --- linux-2.4.0/arch/s390/kernel/s390dyn.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/s390dyn.c Thu Jan 1 01:00:00 1970 @@ -1,36 +0,0 @@ -/* - * arch/s390/kernel/s390dyn.c - * S/390 dynamic device attachment - * - * S390 version - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Ingo Adlung (adlung@de.ibm.com) - */ - -#include - -#include -#include -#include - -int s390_device_register( devreg_t *drinfo ) -{ - return -EOPNOTSUPP; -} - - -int s390_device_deregister ( devreg_t *dreg ) -{ - return -EOPNOTSUPP; -} - -int s390_request_irq_special( int irq, - io_handler_func_t io_handler, - not_oper_handler_func_t not_oper_handler, - unsigned long irqflags, - const char *devname, - void *dev_id) -{ - return -EOPNOTSUPP; -} - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/s390fpu.c linux.ac/arch/s390/kernel/s390fpu.c --- linux-2.4.0/arch/s390/kernel/s390fpu.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/s390fpu.c Fri Jan 5 00:00:32 2001 @@ -13,7 +13,6 @@ * ( & as usual I didn't feel like debugging inline code ). */ -#include #include int save_fp_regs1(s390_fp_regs *fpregs) @@ -81,6 +80,11 @@ { int has_ieee=MACHINE_HAS_IEEE; + /* If we don't mask with the FPC_VALID_MASK here + * we've got a very quick shutdown -h now command + * via a kernel specification exception. + */ + fpregs->fpc&=FPC_VALID_MASK; asm volatile ("LD 0,8(%0)\n\t" "LD 2,24(%0)\n\t" "LD 4,40(%0)\n\t" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/s390io.c linux.ac/arch/s390/kernel/s390io.c --- linux-2.4.0/arch/s390/kernel/s390io.c Sat Aug 5 00:15:37 2000 +++ linux.ac/arch/s390/kernel/s390io.c Thu Jan 1 01:00:00 1970 @@ -1,4605 +0,0 @@ -/* - * arch/s390/kernel/s390io.c - * S/390 common I/O routines - * - * S390 version - * Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, - * IBM Corporation - * Author(s): Ingo Adlung (adlung@de.ibm.com) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#undef CONFIG_DEBUG_IO - -#define REIPL_DEVID_MAGIC 0x87654321 - -struct irqaction init_IRQ_action; -unsigned int highest_subchannel; -ioinfo_t *ioinfo_head = NULL; -ioinfo_t *ioinfo_tail = NULL; -ioinfo_t *ioinfo[__MAX_SUBCHANNELS] = { - [0 ... (__MAX_SUBCHANNELS-1)] = INVALID_STORAGE_AREA -}; - -static spinlock_t sync_isc; // synchronous irq processing lock -static psw_t io_sync_wait; // wait PSW for sync IO, prot. by sync_isc -static psw_t io_new_psw; // save I/O new PSW, prot. by sync_isc -static int cons_dev = -1; // identify console device -static int init_IRQ_complete = 0; -static schib_t init_schib; -static __u64 irq_IPL_TOD; - -/* - * Dummy controller type for unused interrupts - */ -int do_none(unsigned int irq, int cpu, struct pt_regs * regs) { return 0;} -int enable_none(unsigned int irq) { return(-ENODEV); } -int disable_none(unsigned int irq) { return(-ENODEV); } - -struct hw_interrupt_type no_irq_type = { - "none", - do_none, - enable_none, - disable_none -}; - -static void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs); -static int s390_setup_irq(unsigned int irq, struct irqaction * new); -static void s390_process_subchannels( void); -static void s390_device_recognition( void); -static int s390_validate_subchannel( int irq); -static int s390_SenseID( int irq, senseid_t *sid); -static int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid); -static int s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid); -static int s390_process_IRQ( unsigned int irq ); -static int s390_DevicePathVerification( int irq ); - -extern int do_none(unsigned int irq, int cpu, struct pt_regs * regs); -extern int enable_none(unsigned int irq); -extern int disable_none(unsigned int irq); -extern void tod_wait(unsigned long usecs); - -asmlinkage void do_IRQ( struct pt_regs regs, - unsigned int irq, - __u32 s390_intparm ); - -void s390_displayhex(char *str,void *ptr,s32 cnt); - -void s390_displayhex(char *str,void *ptr,s32 cnt) -{ - s32 cnt1,cnt2,maxcnt2; - u32 *currptr=(__u32 *)ptr; - - printk("\n%s\n",str); - - for(cnt1=0;cnt116) - maxcnt2=16; - for(cnt2=0;cnt2= __MAX_SUBCHANNELS) - return -EINVAL; - - if ( !handler || !dev_id ) - return -EINVAL; - - /* - * during init_IRQ() processing we don't have memory - * management yet, thus need to use a statically - * allocated irqaction control block - */ - if ( init_IRQ_complete ) - { - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); - } - else - { - action = &init_IRQ_action; - - } /* endif */ - - if (!action) - { - return -ENOMEM; - - } /* endif */ - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = s390_setup_irq( irq, action); - - if ( !retval ) - { - retval = s390_DevicePathVerification( irq ); - } - else if ( retval && init_IRQ_complete ) - { - kfree(action); - - } /* endif */ - - return retval; -} - -void s390_free_irq(unsigned int irq, void *dev_id) -{ - unsigned int flags; - int ret; - - unsigned int count = 0; - - if ( irq >= __MAX_SUBCHANNELS || ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return; - - } /* endif */ - - s390irq_spin_lock_irqsave( irq, flags); - -#ifdef CONFIG_KERNEL_DEBUG - if ( irq != cons_dev ) - { - printk("Trying to free IRQ%d\n",irq); - - } /* endif */ -#endif - - /* - * disable the device and reset all IRQ info if - * the IRQ is actually owned by the handler ... - */ - if ( ioinfo[irq]->irq_desc.action ) - { - if ( (dev_id == ioinfo[irq]->irq_desc.action->dev_id ) - || (dev_id == (devstat_t *)REIPL_DEVID_MAGIC) ) - { - /* start deregister */ - ioinfo[irq]->ui.flags.unready = 1; - - do - { - ret = ioinfo[irq]->irq_desc.handler->disable(irq); - - count++; - - if ( ret == -EBUSY ) - { - int iret; - - /* - * kill it ! - * ... we first try sync and eventually - * try terminating the current I/O by - * an async request, twice halt, then - * clear. - */ - if ( count < 3 ) - { - iret = halt_IO( irq, - 0xC8C1D3E3, - DOIO_WAIT_FOR_INTERRUPT ); - - if ( iret == -EBUSY ) - { - halt_IO( irq, 0xC8C1D3E3, 0); - s390irq_spin_unlock_irqrestore( irq, flags); - tod_wait( 200000 ); /* 200 ms */ - s390irq_spin_lock_irqsave( irq, flags); - - } /* endif */ - } - else - { - iret = clear_IO( irq, - 0x40C3D3D9, - DOIO_WAIT_FOR_INTERRUPT ); - - if ( iret == -EBUSY ) - { - clear_IO( irq, 0xC8C1D3E3, 0); - s390irq_spin_unlock_irqrestore( irq, flags); - tod_wait( 1000000 ); /* 1000 ms */ - s390irq_spin_lock_irqsave( irq, flags); - - } /* endif */ - - } /* endif */ - - if ( count == 3 ) - { - /* give it a very last try ... */ - ioinfo[irq]->irq_desc.handler->disable(irq); - - if ( ioinfo[irq]->ui.flags.busy ) - { - printk( KERN_CRIT"free_irq(%04X) " - "- device %04X busy, retry " - "count exceeded\n", - irq, - ioinfo[irq]->devstat.devno); - - } /* endif */ - - break; /* sigh, let's give up ... */ - - } /* endif */ - - } /* endif */ - - } while ( ret == -EBUSY ); - - if ( init_IRQ_complete ) - kfree( ioinfo[irq]->irq_desc.action ); - - ioinfo[irq]->irq_desc.action = NULL; - ioinfo[irq]->ui.flags.ready = 0; - - ioinfo[irq]->irq_desc.handler->enable = &enable_none; - ioinfo[irq]->irq_desc.handler->disable = &disable_none; - - ioinfo[irq]->ui.flags.unready = 0; /* deregister ended */ - - s390irq_spin_unlock_irqrestore( irq, flags); - } - else - { - s390irq_spin_unlock_irqrestore( irq, flags); - - printk("free_irq() : error, dev_id does not match !"); - - } /* endif */ - - } - else - { - s390irq_spin_unlock_irqrestore( irq, flags); - - printk("free_irq() : error, no action block ... !"); - - } /* endif */ - -} - -/* - * Generic enable/disable code - */ -int disable_irq(unsigned int irq) -{ - unsigned long flags; - int ret; - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - return( -ENODEV); - - s390irq_spin_lock_irqsave(irq, flags); - - /* - * At this point we may actually have a pending interrupt being active - * on another CPU. So don't touch the IRQ_INPROGRESS bit.. - */ - ioinfo[irq]->irq_desc.status |= IRQ_DISABLED; - ret = ioinfo[irq]->irq_desc.handler->disable(irq); - s390irq_spin_unlock_irqrestore(irq, flags); - - synchronize_irq(); - - return( ret); -} - -int enable_irq(unsigned int irq) -{ - unsigned long flags; - int ret; - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - return( -ENODEV); - - s390irq_spin_lock_irqsave(irq, flags); - - ioinfo[irq]->irq_desc.status = 0; - ret = ioinfo[irq]->irq_desc.handler->enable(irq); - - s390irq_spin_unlock_irqrestore(irq, flags); - - return(ret); -} - -/* - * Enable IRQ by modifying the subchannel - */ -static int enable_subchannel( unsigned int irq) -{ - int ret; - int ccode; - int retry = 5; - - if ( irq > highest_subchannel || irq < 0 ) - { - return( -ENODEV ); - - } /* endif */ - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - return( -ENODEV); - - /* - * If a previous disable request is pending we reset it. However, this - * status implies that the device may (still) be not-operational. - */ - if ( ioinfo[irq]->ui.flags.d_disable ) - { - ioinfo[irq]->ui.flags.d_disable = 0; - ret = 0; - } - else - { - - ccode = stsch(irq, &(ioinfo[irq]->schib) ); - - if ( ccode ) - { - ret = -ENODEV; - } - else - { - ioinfo[irq]->schib.pmcw.ena = 1; - - do - { - ccode = msch( irq, &(ioinfo[irq]->schib) ); - - switch (ccode) { - case 0: - ret = 0; - break; - - case 1: - /* - * very bad, requires interrupt alike - * processing, where "rbh" is a dummy - * parameter for interface compatibility - * only. Bottom-half handling cannot be - * required as this must be an - * unsolicited interrupt (!busy). - */ - - ioinfo[irq]->ui.flags.s_pend = 1; - - s390_process_IRQ( irq ); - - ioinfo[irq]->ui.flags.s_pend = 0; - - ret = -EIO; /* might be overwritten */ - /* ... on re-driving */ - /* ... the msch() */ - retry--; - break; - - case 3: - ioinfo[irq]->ui.flags.oper = 0; - ret = -ENODEV; - break; - - default: - printk( KERN_CRIT"enable_subchannel(%04X) " - " : ccode 2 on msch() for device " - "%04X received !\n", - irq, - ioinfo[irq]->devstat.devno); - ret = -ENODEV; // never reached - } - - } while ( (ccode == 1) && retry ); - - } /* endif */ - - } /* endif */ - - return( ret ); -} - - -/* - * Disable IRQ by modifying the subchannel - */ -static int disable_subchannel( unsigned int irq) -{ - int cc; /* condition code */ - int ret; /* function return value */ - int retry = 5; - - if ( irq > highest_subchannel ) - { - ret = -ENODEV; - } - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - else if ( ioinfo[irq]->ui.flags.busy ) - { - /* - * the disable function must not be called while there are - * requests pending for completion ! - */ - ret = -EBUSY; - } - else - { - /* - * If device isn't operational we have to perform delayed - * disabling when the next interrupt occurs - unless the - * irq is re-requested prior to the interrupt to occur. - */ - cc = stsch(irq, &(ioinfo[irq]->schib) ); - - if ( cc == 3 ) - { - ioinfo[irq]->ui.flags.oper = 0; - ioinfo[irq]->ui.flags.d_disable = 1; - - ret = 0; - } - else // cc == 0 - { - ioinfo[irq]->schib.pmcw.ena = 0; - - do - { - cc = msch( irq, &(ioinfo[irq]->schib) ); - - switch (cc) { - case 0 : - ret = 0; /* done */ - break; - - case 1 : - /* - * very bad, requires interrupt alike - * processing, where "rbh" is a dummy - * parm for interface compatibility - * only. Bottom-half handling cannot - * be required as this must be an - * unsolicited interrupt (!busy). - */ - ioinfo[irq]->ui.flags.s_pend = 1; - s390_process_IRQ( irq ); - ioinfo[irq]->ui.flags.s_pend = 0; - - ret = -EBUSY; /* might be overwritten */ - /* ... on re-driving the */ - /* ... msch() call */ - retry--; - break; - - case 2 : - /* - * *** must not occur ! *** - * *** *** - * *** indicates our internal *** - * *** interrupt accounting is out *** - * *** of sync ===> panic() *** - */ - printk( KERN_CRIT"disable_subchannel(%04X) " - "- unexpected busy condition for " - "device %04X received !\n", - irq, - ioinfo[irq]->devstat.devno); - - ret = -ENODEV; // never reached - break; - - case 3 : - /* - * should hardly occur ?! - */ - ioinfo[irq]->ui.flags.oper = 0; - ioinfo[irq]->ui.flags.d_disable = 1; - - ret = 0; /* if the device has gone we */ - /* ... don't need to disable */ - /* ... it anymore ! */ - break; - - default : - ret = -ENODEV; // never reached ... - break; - - } /* endswitch */ - - } while ( (cc == 1) && retry ); - - } /* endif */ - - } /* endif */ - - return( ret); -} - - - -int s390_setup_irq( unsigned int irq, struct irqaction * new) -{ - unsigned long flags; - int rc = 0; - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - - /* - * The following block of code has to be executed atomically - */ - s390irq_spin_lock_irqsave( irq, flags); - - if ( ioinfo[irq]->irq_desc.action == NULL ) - { - ioinfo[irq]->irq_desc.action = new; - ioinfo[irq]->irq_desc.status = 0; - ioinfo[irq]->irq_desc.handler->enable = &enable_subchannel; - ioinfo[irq]->irq_desc.handler->disable = &disable_subchannel; - ioinfo[irq]->irq_desc.handler->handle = &handle_IRQ_event; - - ioinfo[irq]->ui.flags.ready = 1; - - ioinfo[irq]->irq_desc.handler->enable(irq); - } - else - { - /* - * interrupt already owned, and shared interrupts - * aren't supported on S/390. - */ - rc = -EBUSY; - - } /* endif */ - - s390irq_spin_unlock_irqrestore(irq,flags); - - return( rc); -} - -void s390_init_IRQ( void ) -{ - unsigned long flags; /* PSW flags */ - long cr6 __attribute__ ((aligned (8))); - - // Hopefully bh_count's will get set when we copy the prefix lowcore - // structure to other CPI's ( DJB ) - softirq_active(smp_processor_id()) = 0; - softirq_mask(smp_processor_id()) = 0; - local_bh_count(smp_processor_id()) = 0; - local_irq_count(smp_processor_id()) = 0; - syscall_count(smp_processor_id()) = 0; - - asm volatile ("STCK %0" : "=m" (irq_IPL_TOD)); - - /* - * As we don't know about the calling environment - * we assure running disabled. Before leaving the - * function we resestablish the old environment. - * - * Note : as we don't need a system wide lock, therefore - * we shouldn't use cli(), but __cli() as this - * affects the current CPU only. - */ - __save_flags(flags); - __cli(); - - /* - * disable all interrupts - */ - cr6 = 0; - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - s390_process_subchannels(); - - /* - * enable default I/O-interrupt sublass 3 - */ - cr6 = 0x10000000; - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - s390_device_recognition(); - - init_IRQ_complete = 1; - - s390_init_machine_check(); - - __restore_flags(flags); - - return; -} - - -/* - * dummy handler, used during init_IRQ() processing for compatibility only - */ -void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs) -{ - /* this is a dummy handler only ... */ -} - - -int s390_start_IO( int irq, /* IRQ */ - ccw1_t *cpa, /* logical channel prog addr */ - unsigned long user_intparm, /* interruption parameter */ - __u8 lpm, /* logical path mask */ - unsigned long flag) /* flags */ -{ - int ccode; - unsigned long psw_flags; - - int sync_isc_locked = 0; - int ret = 0; - - /* - * The flag usage is mutal exclusive ... - */ - if ( (flag & DOIO_RETURN_CHAN_END) - && (flag & DOIO_REPORT_ALL ) ) - { - return( -EINVAL ); - - } /* endif */ - - memset( &(ioinfo[irq]->orb), '\0', sizeof( orb_t) ); - - /* - * setup ORB - */ - ioinfo[irq]->orb.intparm = (__u32)&ioinfo[irq]->u_intparm; - ioinfo[irq]->orb.fmt = 1; - - ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH); - ioinfo[irq]->orb.spnd = (flag & DOIO_ALLOW_SUSPEND); - ioinfo[irq]->orb.ssic = ( (flag & DOIO_ALLOW_SUSPEND ) - && (flag & DOIO_SUPPRESS_INTER) ); - - if ( flag & DOIO_VALID_LPM ) - { - ioinfo[irq]->orb.lpm = lpm; - } - else - { - ioinfo[irq]->orb.lpm = ioinfo[irq]->opm; - - } /* endif */ - - ioinfo[irq]->orb.cpa = (__u32)virt_to_phys( cpa); - - /* - * If sync processing was requested we lock the sync ISC, modify the - * device to present interrupts for this ISC only and switch the - * CPU to handle this ISC + the console ISC exclusively. - */ - if ( flag & DOIO_WAIT_FOR_INTERRUPT ) - { - // - // check whether we run recursively (sense processing) - // - if ( !ioinfo[irq]->ui.flags.syncio ) - { - spin_lock_irqsave( &sync_isc, psw_flags); - - ret = enable_cpu_sync_isc( irq); - - if ( ret ) - { - spin_unlock_irqrestore( &sync_isc, psw_flags); - return( ret); - } - else - { - sync_isc_locked = 1; // local - ioinfo[irq]->ui.flags.syncio = 1; // global - - } /* endif */ - - } /* endif */ - - } /* endif */ - - /* - * Issue "Start subchannel" and process condition code - */ - ccode = ssch( irq, &(ioinfo[irq]->orb) ); - - switch ( ccode ) { - case 0: - - if ( !ioinfo[irq]->ui.flags.w4sense ) - { - /* - * init the device driver specific devstat irb area - * - * Note : don´t clear saved irb info in case of sense ! - */ - memset( &((devstat_t *)ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, - '\0', sizeof( irb_t) ); - } /* endif */ - - /* - * initialize device status information - */ - ioinfo[irq]->ui.flags.busy = 1; - ioinfo[irq]->ui.flags.doio = 1; - - ioinfo[irq]->u_intparm = user_intparm; - ioinfo[irq]->devstat.cstat = 0; - ioinfo[irq]->devstat.dstat = 0; - ioinfo[irq]->devstat.lpum = 0; - ioinfo[irq]->devstat.flag = DEVSTAT_START_FUNCTION; - ioinfo[irq]->devstat.scnt = 0; - - ioinfo[irq]->ui.flags.fast = 0; - ioinfo[irq]->ui.flags.repall = 0; - - /* - * Check for either early (FAST) notification requests - * or if we are to return all interrupt info. - * Default is to call IRQ handler at secondary status only - */ - if ( flag & DOIO_RETURN_CHAN_END ) - { - ioinfo[irq]->ui.flags.fast = 1; - } - else if ( flag & DOIO_REPORT_ALL ) - { - ioinfo[irq]->ui.flags.repall = 1; - - } /* endif */ - - ioinfo[irq]->ulpm = ioinfo[irq]->orb.lpm; - - /* - * If synchronous I/O processing is requested, we have - * to wait for the corresponding interrupt to occur by - * polling the interrupt condition. However, as multiple - * interrupts may be outstanding, we must not just wait - * for the first interrupt, but must poll until ours - * pops up. - */ - if ( flag & DOIO_WAIT_FOR_INTERRUPT ) - { - // __u32 io_parm; - psw_t io_new_psw; - int ccode; - - int ready = 0; - int io_sub = -1; - struct _lowcore *lc = NULL; - int count = 30000; - - /* - * We shouldn't perform a TPI loop, waiting for an - * interrupt to occur, but should load a WAIT PSW - * instead. Otherwise we may keep the channel subsystem - * busy, not able to present the interrupt. When our - * sync. interrupt arrived we reset the I/O old PSW to - * its original value. - */ - memcpy( &io_new_psw, &lc->io_new_psw, sizeof(psw_t)); - - ccode = iac(); - - switch (ccode) { - case 0: // primary-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_PRIM_SPACE_MODE - | _PSW_IO_WAIT; - break; - case 1: // secondary-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_SEC_SPACE_MODE - | _PSW_IO_WAIT; - break; - case 2: // access-register - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_ACC_REG_MODE - | _PSW_IO_WAIT; - break; - case 3: // home-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_HOME_SPACE_MODE - | _PSW_IO_WAIT; - break; - default: - panic( "start_IO() : unexpected " - "address-space-control %d\n", - ccode); - break; - } /* endswitch */ - - io_sync_wait.addr = FIX_PSW(&&io_wakeup); - - /* - * Martin didn't like modifying the new PSW, now we take - * a fast exit in do_IRQ() instead - */ - *(__u32 *)__LC_SYNC_IO_WORD = 1; - - do - { - if ( flag & DOIO_TIMEOUT ) - { - tpi_info_t tpi_info; - - do - { - if ( tpi(&tpi_info) == 1 ) - { - io_sub = tpi_info.irq; - break; - } - else - { - count--; - tod_wait(100); /* usecs */ - - } /* endif */ - - } while ( count ); - } - else - { - asm volatile ("lpsw %0" : : "m" (io_sync_wait)); - -io_wakeup: - io_sub = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR; - - } /* endif */ - - if ( count ) - ready = s390_process_IRQ( io_sub ); - - /* - * surrender when retry count's exceeded ... - */ - - } while ( !( ( io_sub == irq ) - && ( ready == 1 )) - && count ); - - *(__u32 *)__LC_SYNC_IO_WORD = 0; - - if ( !count ) - ret = -ETIMEDOUT; - - } /* endif */ - - break; - - case 1 : /* status pending */ - - ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; - - /* - * initialize the device driver specific devstat irb area - */ - memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, - '\0', sizeof( irb_t) ); - - /* - * Let the common interrupt handler process the pending status. - * However, we must avoid calling the user action handler, as - * it won't be prepared to handle a pending status during - * do_IO() processing inline. This also implies that process_IRQ - * must terminate synchronously - especially if device sensing - * is required. - */ - ioinfo[irq]->ui.flags.s_pend = 1; - ioinfo[irq]->ui.flags.busy = 1; - ioinfo[irq]->ui.flags.doio = 1; - - s390_process_IRQ( irq ); - - ioinfo[irq]->ui.flags.s_pend = 0; - ioinfo[irq]->ui.flags.busy = 0; - ioinfo[irq]->ui.flags.doio = 0; - ioinfo[irq]->ui.flags.repall = 0; - ioinfo[irq]->ui.flags.w4final = 0; - - ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; - - /* - * In multipath mode a condition code 3 implies the last path - * has gone, except we have previously restricted the I/O to - * a particular path. A condition code 1 (0 won't occur) - * results in return code EIO as well as 3 with another path - * than the one used (i.e. path available mask is non-zero). - */ - if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 ) - { - ret = -ENODEV; - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - ioinfo[irq]->ui.flags.oper = 0; - -#if CONFIG_DEBUG_IO - { - char buffer[80]; - - stsch(irq, &(ioinfo[irq]->schib) ); - - sprintf( buffer, "s390_start_IO(%04X) - irb for " - "device %04X, after status pending\n", - irq, - ioinfo[irq]->devstat.devno ); - - s390_displayhex( buffer, - &(ioinfo[irq]->devstat.ii.irb) , - sizeof(irb_t)); - - sprintf( buffer, "s390_start_IO(%04X) - schib for " - "device %04X, after status pending\n", - irq, - ioinfo[irq]->devstat.devno ); - - s390_displayhex( buffer, - &(ioinfo[irq]->schib) , - sizeof(schib_t)); - - - if (ioinfo[irq]->devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL) - { - sprintf( buffer, "s390_start_IO(%04X) - sense " - "data for " - "device %04X, after status pending\n", - irq, - ioinfo[irq]->devstat.devno ); - - s390_displayhex( buffer, - ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->ii.sense.data, - ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->rescnt); - - } - } -#endif - } - else - { - ret = -EIO; - ioinfo[irq]->devstat.flag &= ~DEVSTAT_NOT_OPER; - ioinfo[irq]->ui.flags.oper = 1; - - } /* endif */ - - break; - - case 2 : /* busy */ - - ret = -EBUSY; - break; - - default: /* device not operational */ - - ret = -ENODEV; - ioinfo[irq]->ui.flags.oper = 0; - - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - - memcpy( ioinfo[irq]->irq_desc.action->dev_id, - &(ioinfo[irq]->devstat), - sizeof( devstat_t) ); - -#if CONFIG_DEBUG_IO - { - char buffer[80]; - - stsch(irq, &(ioinfo[irq]->schib) ); - - sprintf( buffer, "s390_start_IO(%04X) - schib for " - "device %04X, after 'not oper' status\n", - irq, - ioinfo[irq]->devstat.devno ); - - s390_displayhex( buffer, - &(ioinfo[irq]->schib), - sizeof(schib_t)); - } -#endif - break; - - } /* endswitch */ - - if ( ( flag & DOIO_WAIT_FOR_INTERRUPT ) - && ( sync_isc_locked ) ) - { - disable_cpu_sync_isc( irq ); - - spin_unlock_irqrestore( &sync_isc, psw_flags); - - sync_isc_locked = 0; // local setting - ioinfo[irq]->ui.flags.syncio = 0; // global setting - - } /* endif */ - - return( ret); -} - -int do_IO( int irq, /* IRQ */ - ccw1_t *cpa, /* channel program address */ - unsigned long user_intparm, /* interruption parameter */ - __u8 lpm, /* logical path mask */ - unsigned long flag) /* flags : see above */ -{ - int ret = 0; - - if ( irq > highest_subchannel || irq < 0 ) - { - return( -ENODEV ); - - } /* endif */ - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - - /* handler registered ? or free_irq() in process already ? */ - if ( !ioinfo[irq]->ui.flags.ready || ioinfo[irq]->ui.flags.unready ) - { - return( -ENODEV ); - - } /* endif */ - - /* - * Note: We ignore the device operational status - if not operational, - * the SSCH will lead to an -ENODEV condition ... - */ - if ( !ioinfo[irq]->ui.flags.busy ) /* last I/O completed ? */ - { - ret = s390_start_IO( irq, cpa, user_intparm, lpm, flag); - } - else if ( ioinfo[irq]->ui.flags.fast ) - { - /* - * If primary status was received and ending status is missing, - * the device driver won't be notified on the ending status - * if early (fast) interrupt notification was requested. - * Therefore we have to queue the next incoming request. If - * halt_IO() is issued while there is a request queued, a HSCH - * needs to be issued and the queued request must be deleted - * but its intparm must be returned (see halt_IO() processing) - */ - if ( ioinfo[irq]->ui.flags.w4final - && !ioinfo[irq]->ui.flags.doio_q ) - { - ioinfo[irq]->qflag = flag; - ioinfo[irq]->qcpa = cpa; - ioinfo[irq]->qintparm = user_intparm; - ioinfo[irq]->qlpm = lpm; - } - else - { - ret = -EBUSY; - - } /* endif */ - } - else - { - ret = -EBUSY; - - } /* endif */ - - return( ret ); - -} - -/* - * resume suspended I/O operation - */ -int resume_IO( int irq) -{ - int ret = 0; - - if ( irq > highest_subchannel || irq < 0 ) - { - return( -ENODEV ); - - } /* endif */ - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - - /* - * We allow for 'resume' requests only for active I/O operations - */ - if ( ioinfo[irq]->ui.flags.busy ) - { - int ccode; - - ccode = rsch( irq); - - switch (ccode) { - case 0 : - break; - - case 1 : - s390_process_IRQ( irq ); - ret = -EBUSY; - break; - - case 2 : - ret = -EINVAL; - break; - - case 3 : - /* - * useless to wait for request completion - * as device is no longer operational ! - */ - ioinfo[irq]->ui.flags.oper = 0; - ioinfo[irq]->ui.flags.busy = 0; - ret = -ENODEV; - break; - - } /* endswitch */ - - } - else - { - ret = -ENOTCONN; - - } /* endif */ - - return( ret); -} - -/* - * Note: The "intparm" parameter is not used by the halt_IO() function - * itself, as no ORB is built for the HSCH instruction. However, - * it allows the device interrupt handler to associate the upcoming - * interrupt with the halt_IO() request. - */ -int halt_IO( int irq, - unsigned long user_intparm, - unsigned long flag) /* possible DOIO_WAIT_FOR_INTERRUPT */ -{ - int ret; - int ccode; - unsigned long psw_flags; - - int sync_isc_locked = 0; - - if ( irq > highest_subchannel || irq < 0 ) - { - ret = -ENODEV; - } - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - - /* - * we only allow for halt_IO if the device has an I/O handler associated - */ - else if ( !ioinfo[irq]->ui.flags.ready ) - { - ret = -ENODEV; - } - /* - * we ignore the halt_io() request if ending_status was received but - * a SENSE operation is waiting for completion. - */ - else if ( ioinfo[irq]->ui.flags.w4sense ) - { - ret = 0; - } - /* - * We don't allow for halt_io with a sync do_IO() requests pending. - */ - else if ( ioinfo[irq]->ui.flags.syncio ) - { - ret = -EBUSY; - } - else - { - /* - * If sync processing was requested we lock the sync ISC, - * modify the device to present interrupts for this ISC only - * and switch the CPU to handle this ISC + the console ISC - * exclusively. - */ - if ( flag & DOIO_WAIT_FOR_INTERRUPT ) - { - // - // check whether we run recursively (sense processing) - // - if ( !ioinfo[irq]->ui.flags.syncio ) - { - spin_lock_irqsave( &sync_isc, psw_flags); - - ret = enable_cpu_sync_isc( irq); - - if ( ret ) - { - spin_unlock_irqrestore( &sync_isc, - psw_flags); - return( ret); - } - else - { - sync_isc_locked = 1; // local - ioinfo[irq]->ui.flags.syncio = 1; // global - - } /* endif */ - - } /* endif */ - - } /* endif */ - - /* - * Issue "Halt subchannel" and process condition code - */ - ccode = hsch( irq ); - - switch ( ccode ) { - case 0: - - ioinfo[irq]->ui.flags.haltio = 1; - - if ( !ioinfo[irq]->ui.flags.doio ) - { - ioinfo[irq]->ui.flags.busy = 1; - ioinfo[irq]->u_intparm = user_intparm; - ioinfo[irq]->devstat.cstat = 0; - ioinfo[irq]->devstat.dstat = 0; - ioinfo[irq]->devstat.lpum = 0; - ioinfo[irq]->devstat.flag = DEVSTAT_HALT_FUNCTION; - ioinfo[irq]->devstat.scnt = 0; - - } - else - { - ioinfo[irq]->devstat.flag |= DEVSTAT_HALT_FUNCTION; - - } /* endif */ - - /* - * If synchronous I/O processing is requested, we have - * to wait for the corresponding interrupt to occur by - * polling the interrupt condition. However, as multiple - * interrupts may be outstanding, we must not just wait - * for the first interrupt, but must poll until ours - * pops up. - */ - if ( flag & DOIO_WAIT_FOR_INTERRUPT ) - { - int io_sub; - __u32 io_parm; - psw_t io_new_psw; - int ccode; - - int ready = 0; - struct _lowcore *lc = NULL; - - /* - * We shouldn't perform a TPI loop, waiting for - * an interrupt to occur, but should load a - * WAIT PSW instead. Otherwise we may keep the - * channel subsystem busy, not able to present - * the interrupt. When our sync. interrupt - * arrived we reset the I/O old PSW to its - * original value. - */ - memcpy( &io_new_psw, - &lc->io_new_psw, - sizeof(psw_t)); - - ccode = iac(); - - switch (ccode) { - case 0: // primary-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_PRIM_SPACE_MODE - | _PSW_IO_WAIT; - break; - case 1: // secondary-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_SEC_SPACE_MODE - | _PSW_IO_WAIT; - break; - case 2: // access-register - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_ACC_REG_MODE - | _PSW_IO_WAIT; - break; - case 3: // home-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_HOME_SPACE_MODE - | _PSW_IO_WAIT; - break; - default: - panic( "halt_IO() : unexpected " - "address-space-control %d\n", - ccode); - break; - } /* endswitch */ - - io_sync_wait.addr = FIX_PSW(&&hio_wakeup); - - /* - * Martin didn't like modifying the new PSW, now we take - * a fast exit in do_IRQ() instead - */ - *(__u32 *)__LC_SYNC_IO_WORD = 1; - - do - { - - asm volatile ( "lpsw %0" : : "m" (io_sync_wait) ); -hio_wakeup: - io_parm = *(__u32 *)__LC_IO_INT_PARM; - io_sub = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR; - - ready = s390_process_IRQ( io_sub ); - - } while ( !((io_sub == irq) && (ready == 1)) ); - - *(__u32 *)__LC_SYNC_IO_WORD = 0; - - } /* endif */ - - ret = 0; - break; - - case 1 : /* status pending */ - - ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; - - /* - * initialize the device driver specific devstat irb area - */ - memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, - '\0', sizeof( irb_t) ); - - /* - * Let the common interrupt handler process the pending - * status. However, we must avoid calling the user - * action handler, as it won't be prepared to handle - * a pending status during do_IO() processing inline. - * This also implies that s390_process_IRQ must - * terminate synchronously - especially if device - * sensing is required. - */ - ioinfo[irq]->ui.flags.s_pend = 1; - ioinfo[irq]->ui.flags.busy = 1; - ioinfo[irq]->ui.flags.doio = 1; - - s390_process_IRQ( irq ); - - ioinfo[irq]->ui.flags.s_pend = 0; - ioinfo[irq]->ui.flags.busy = 0; - ioinfo[irq]->ui.flags.doio = 0; - ioinfo[irq]->ui.flags.repall = 0; - ioinfo[irq]->ui.flags.w4final = 0; - - ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; - - /* - * In multipath mode a condition code 3 implies the last - * path has gone, except we have previously restricted - * the I/O to a particular path. A condition code 1 - * (0 won't occur) results in return code EIO as well - * as 3 with another path than the one used (i.e. path available mask is non-zero). - */ - if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 ) - { - ret = -ENODEV; - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - ioinfo[irq]->ui.flags.oper = 0; - } - else - { - ret = -EIO; - ioinfo[irq]->devstat.flag &= ~DEVSTAT_NOT_OPER; - ioinfo[irq]->ui.flags.oper = 1; - - } /* endif */ - - break; - - case 2 : /* busy */ - - ret = -EBUSY; - break; - - default: /* device not operational */ - - ret = -ENODEV; - break; - - } /* endswitch */ - - if ( ( flag & DOIO_WAIT_FOR_INTERRUPT ) - && ( sync_isc_locked ) ) - { - sync_isc_locked = 0; // local setting - ioinfo[irq]->ui.flags.syncio = 0; // global setting - - disable_cpu_sync_isc( irq ); - - spin_unlock_irqrestore( &sync_isc, psw_flags); - - } /* endif */ - - } /* endif */ - - return( ret ); -} - -/* - * Note: The "intparm" parameter is not used by the clear_IO() function - * itself, as no ORB is built for the CSCH instruction. However, - * it allows the device interrupt handler to associate the upcoming - * interrupt with the clear_IO() request. - */ -int clear_IO( int irq, - unsigned long user_intparm, - unsigned long flag) /* possible DOIO_WAIT_FOR_INTERRUPT */ -{ - int ret; - int ccode; - unsigned long psw_flags; - - int sync_isc_locked = 0; - - if ( irq > highest_subchannel || irq < 0 ) - { - ret = -ENODEV; - } - - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - - /* - * we only allow for halt_IO if the device has an I/O handler associated - */ - else if ( !ioinfo[irq]->ui.flags.ready ) - { - ret = -ENODEV; - } - /* - * we ignore the halt_io() request if ending_status was received but - * a SENSE operation is waiting for completion. - */ - else if ( ioinfo[irq]->ui.flags.w4sense ) - { - ret = 0; - } - /* - * We don't allow for halt_io with a sync do_IO() requests pending. - * Concurrent I/O is possible in SMP environments only, but the - * sync. I/O request can be gated to one CPU at a time only. - */ - else if ( ioinfo[irq]->ui.flags.syncio ) - { - ret = -EBUSY; - } - else - { - /* - * If sync processing was requested we lock the sync ISC, - * modify the device to present interrupts for this ISC only - * and switch the CPU to handle this ISC + the console ISC - * exclusively. - */ - if ( flag & DOIO_WAIT_FOR_INTERRUPT ) - { - // - // check whether we run recursively (sense processing) - // - if ( !ioinfo[irq]->ui.flags.syncio ) - { - spin_lock_irqsave( &sync_isc, psw_flags); - - ret = enable_cpu_sync_isc( irq); - - if ( ret ) - { - spin_unlock_irqrestore( &sync_isc, - psw_flags); - return( ret); - } - else - { - sync_isc_locked = 1; // local - ioinfo[irq]->ui.flags.syncio = 1; // global - - } /* endif */ - - } /* endif */ - - } /* endif */ - - /* - * Issue "Halt subchannel" and process condition code - */ - ccode = csch( irq ); - - switch ( ccode ) { - case 0: - - ioinfo[irq]->ui.flags.haltio = 1; - - if ( !ioinfo[irq]->ui.flags.doio ) - { - ioinfo[irq]->ui.flags.busy = 1; - ioinfo[irq]->u_intparm = user_intparm; - ioinfo[irq]->devstat.cstat = 0; - ioinfo[irq]->devstat.dstat = 0; - ioinfo[irq]->devstat.lpum = 0; - ioinfo[irq]->devstat.flag = DEVSTAT_CLEAR_FUNCTION; - ioinfo[irq]->devstat.scnt = 0; - - } - else - { - ioinfo[irq]->devstat.flag |= DEVSTAT_CLEAR_FUNCTION; - - } /* endif */ - - /* - * If synchronous I/O processing is requested, we have - * to wait for the corresponding interrupt to occur by - * polling the interrupt condition. However, as multiple - * interrupts may be outstanding, we must not just wait - * for the first interrupt, but must poll until ours - * pops up. - */ - if ( flag & DOIO_WAIT_FOR_INTERRUPT ) - { - int io_sub; - __u32 io_parm; - psw_t io_new_psw; - int ccode; - - int ready = 0; - struct _lowcore *lc = NULL; - - /* - * We shouldn't perform a TPI loop, waiting for - * an interrupt to occur, but should load a - * WAIT PSW instead. Otherwise we may keep the - * channel subsystem busy, not able to present - * the interrupt. When our sync. interrupt - * arrived we reset the I/O old PSW to its - * original value. - */ - memcpy( &io_new_psw, - &lc->io_new_psw, - sizeof(psw_t)); - - ccode = iac(); - - switch (ccode) { - case 0: // primary-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_PRIM_SPACE_MODE - | _PSW_IO_WAIT; - break; - case 1: // secondary-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_SEC_SPACE_MODE - | _PSW_IO_WAIT; - break; - case 2: // access-register - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_ACC_REG_MODE - | _PSW_IO_WAIT; - break; - case 3: // home-space - io_sync_wait.mask = _IO_PSW_MASK - | _PSW_HOME_SPACE_MODE - | _PSW_IO_WAIT; - break; - default: - panic( "halt_IO() : unexpected " - "address-space-control %d\n", - ccode); - break; - } /* endswitch */ - - io_sync_wait.addr = FIX_PSW(&&cio_wakeup); - - /* - * Martin didn't like modifying the new PSW, now we take - * a fast exit in do_IRQ() instead - */ - *(__u32 *)__LC_SYNC_IO_WORD = 1; - - do - { - - asm volatile ( "lpsw %0" : : "m" (io_sync_wait) ); -cio_wakeup: - io_parm = *(__u32 *)__LC_IO_INT_PARM; - io_sub = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR; - - ready = s390_process_IRQ( io_sub ); - - } while ( !((io_sub == irq) && (ready == 1)) ); - - *(__u32 *)__LC_SYNC_IO_WORD = 0; - - } /* endif */ - - ret = 0; - break; - - case 1 : /* status pending */ - - ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; - - /* - * initialize the device driver specific devstat irb area - */ - memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb, - '\0', sizeof( irb_t) ); - - /* - * Let the common interrupt handler process the pending - * status. However, we must avoid calling the user - * action handler, as it won't be prepared to handle - * a pending status during do_IO() processing inline. - * This also implies that s390_process_IRQ must - * terminate synchronously - especially if device - * sensing is required. - */ - ioinfo[irq]->ui.flags.s_pend = 1; - ioinfo[irq]->ui.flags.busy = 1; - ioinfo[irq]->ui.flags.doio = 1; - - s390_process_IRQ( irq ); - - ioinfo[irq]->ui.flags.s_pend = 0; - ioinfo[irq]->ui.flags.busy = 0; - ioinfo[irq]->ui.flags.doio = 0; - ioinfo[irq]->ui.flags.repall = 0; - ioinfo[irq]->ui.flags.w4final = 0; - - ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; - - /* - * In multipath mode a condition code 3 implies the last - * path has gone, except we have previously restricted - * the I/O to a particular path. A condition code 1 - * (0 won't occur) results in return code EIO as well - * as 3 with another path than the one used (i.e. path available mask is non-zero). - */ - if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 ) - { - ret = -ENODEV; - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - ioinfo[irq]->ui.flags.oper = 0; - } - else - { - ret = -EIO; - ioinfo[irq]->devstat.flag &= ~DEVSTAT_NOT_OPER; - ioinfo[irq]->ui.flags.oper = 1; - - } /* endif */ - - break; - - case 2 : /* busy */ - - ret = -EBUSY; - break; - - default: /* device not operational */ - - ret = -ENODEV; - break; - - } /* endswitch */ - - if ( ( flag & DOIO_WAIT_FOR_INTERRUPT ) - && ( sync_isc_locked ) ) - { - sync_isc_locked = 0; // local setting - ioinfo[irq]->ui.flags.syncio = 0; // global setting - - disable_cpu_sync_isc( irq ); - - spin_unlock_irqrestore( &sync_isc, psw_flags); - - } /* endif */ - - } /* endif */ - - return( ret ); -} - - -/* - * do_IRQ() handles all normal I/O device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - * - * Returns: 0 - no ending status received, no further action taken - * 1 - interrupt handler was called with ending status - */ -asmlinkage void do_IRQ( struct pt_regs regs, - unsigned int irq, - __u32 s390_intparm ) -{ -#ifdef CONFIG_FAST_IRQ - int ccode; - tpi_info_t tpi_info; - int new_irq; -#endif - int use_irq = irq; -// __u32 use_intparm = s390_intparm; - - // - // fix me !!! - // - // We need to schedule device recognition, the interrupt stays - // pending. We need to dynamically allocate an ioinfo structure. - // - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return; /* this keeps the device boxed ... */ - } - - /* - * take fast exit if CPU is in sync. I/O state - * - * Note: we have to turn off the WAIT bit and re-disable - * interrupts prior to return as this was the initial - * entry condition to synchronous I/O. - */ - if ( *(__u32 *)__LC_SYNC_IO_WORD ) - { - regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT); - - return; - - } /* endif */ - - s390irq_spin_lock(use_irq); - -#ifdef CONFIG_FAST_IRQ - do { -#endif /* CONFIG_FAST_IRQ */ - - s390_process_IRQ( use_irq ); - -#ifdef CONFIG_FAST_IRQ - - /* - * more interrupts pending ? - */ - ccode = tpi( &tpi_info ); - - if ( ! ccode ) - break; // no, leave ... - - new_irq = tpi_info.irq; -// use_intparm = tpi_info.intparm; - - /* - * if the interrupt is for a different irq we - * release the current irq lock and obtain - * a new one ... - */ - if ( new_irq != use_irq ) - { - s390irq_spin_unlock(use_irq); - use_irq = new_irq; - s390irq_spin_lock(use_irq); - - } /* endif */ - - } while ( 1 ); - -#endif /* CONFIG_FAST_IRQ */ - - s390irq_spin_unlock(use_irq); - - return; -} - -/* - * s390_process_IRQ() handles status pending situations and interrupts - * - * Called by : do_IRQ() - for "real" interrupts - * s390_start_IO, halt_IO() - * - status pending cond. after SSCH, or HSCH - * disable_subchannel() - status pending conditions (after MSCH) - * - * Returns: 0 - no ending status received, no further action taken - * 1 - interrupt handler was called with ending status - */ -int s390_process_IRQ( unsigned int irq ) -{ - int ccode; /* condition code from tsch() operation */ - int irb_cc; /* condition code from irb */ - int sdevstat; /* effective struct devstat size to copy */ - unsigned int fctl; /* function control */ - unsigned int stctl; /* status control */ - unsigned int actl; /* activity control */ - struct irqaction *action; - struct pt_regs regs; /* for interface compatibility only */ - - int issense = 0; - int ending_status = 0; - int allow4handler = 1; - int chnchk = 0; -#if 0 - int cpu = smp_processor_id(); - - kstat.irqs[cpu][irq]++; -#endif - action = ioinfo[irq]->irq_desc.action; - - /* - * It might be possible that a device was not-oper. at the time - * of free_irq() processing. This means the handler is no longer - * available when the device possibly becomes ready again. In - * this case we perform delayed disable_subchannel() processing. - */ - if ( action == NULL ) - { - if ( !ioinfo[irq]->ui.flags.d_disable ) - { - printk( KERN_CRIT"s390_process_IRQ(%04X) " - "- no interrupt handler registered" - "for device %04X !\n", - irq, - ioinfo[irq]->devstat.devno); - - } /* endif */ - - } /* endif */ - - /* - * retrieve the i/o interrupt information (irb), - * update the device specific status information - * and possibly call the interrupt handler. - * - * Note 1: At this time we don't process the resulting - * condition code (ccode) from tsch(), although - * we probably should. - * - * Note 2: Here we will have to check for channel - * check conditions and call a channel check - * handler. - * - * Note 3: If a start function was issued, the interruption - * parameter relates to it. If a halt function was - * issued for an idle device, the intparm must not - * be taken from lowcore, but from the devstat area. - */ - ccode = tsch( irq, &(ioinfo[irq]->devstat.ii.irb) ); - - // - // We must only accumulate the status if initiated by do_IO() or halt_IO() - // - if ( ioinfo[irq]->ui.flags.busy ) - { - ioinfo[irq]->devstat.dstat |= ioinfo[irq]->devstat.ii.irb.scsw.dstat; - ioinfo[irq]->devstat.cstat |= ioinfo[irq]->devstat.ii.irb.scsw.cstat; - } - else - { - ioinfo[irq]->devstat.dstat = ioinfo[irq]->devstat.ii.irb.scsw.dstat; - ioinfo[irq]->devstat.cstat = ioinfo[irq]->devstat.ii.irb.scsw.cstat; - - ioinfo[irq]->devstat.flag = 0; // reset status flags - - } /* endif */ - - ioinfo[irq]->devstat.lpum = ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum; - - if ( ioinfo[irq]->ui.flags.busy) - { - ioinfo[irq]->devstat.intparm = ioinfo[irq]->u_intparm; - - } /* endif */ - - /* - * reset device-busy bit if no longer set in irb - */ - if ( (ioinfo[irq]->devstat.dstat & DEV_STAT_BUSY ) - && ((ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0)) - { - ioinfo[irq]->devstat.dstat &= ~DEV_STAT_BUSY; - - } /* endif */ - - /* - * Save residual count and CCW information in case primary and - * secondary status are presented with different interrupts. - */ - if ( ioinfo[irq]->devstat.ii.irb.scsw.stctl & SCSW_STCTL_PRIM_STATUS ) - { - ioinfo[irq]->devstat.rescnt = ioinfo[irq]->devstat.ii.irb.scsw.count; - -#if CONFIG_DEBUG_IO - if ( irq != cons_dev ) - printk( "s390_process_IRQ( %04X ) : " - "residual count from irb after tsch() %d\n", - irq, ioinfo[irq]->devstat.rescnt ); -#endif - } /* endif */ - - if ( ioinfo[irq]->devstat.ii.irb.scsw.cpa != 0 ) - { - ioinfo[irq]->devstat.cpa = ioinfo[irq]->devstat.ii.irb.scsw.cpa; - - } /* endif */ - - irb_cc = ioinfo[irq]->devstat.ii.irb.scsw.cc; - - // - // check for any kind of channel or interface control check but don't - // issue the message for the console device - // - if ( (ioinfo[irq]->devstat.ii.irb.scsw.cstat - & ( SCHN_STAT_CHN_DATA_CHK - | SCHN_STAT_CHN_CTRL_CHK - | SCHN_STAT_INTF_CTRL_CHK ) ) - && (irq != cons_dev ) ) - { - printk( "Channel-Check or Interface-Control-Check " - "received\n" - " ... device %04X on subchannel %04X, dev_stat " - ": %02X sch_stat : %02X\n", - ioinfo[irq]->devstat.devno, - irq, - ioinfo[irq]->devstat.dstat, - ioinfo[irq]->devstat.cstat); - - chnchk = 1; - - } /* endif */ - - issense = ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.cons; - - if ( issense ) - { - ioinfo[irq]->devstat.scnt = - ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.scnt; - ioinfo[irq]->devstat.flag |= - DEVSTAT_FLAG_SENSE_AVAIL; - - sdevstat = sizeof( devstat_t); - -#if CONFIG_DEBUG_IO - if ( irq != cons_dev ) - printk( "s390_process_IRQ( %04X ) : " - "concurrent sense bytes avail %d\n", - irq, ioinfo[irq]->devstat.scnt ); -#endif - } - else - { - /* don't copy the sense data area ! */ - sdevstat = sizeof( devstat_t) - SENSE_MAX_COUNT; - - } /* endif */ - - switch ( irb_cc ) { - case 1: /* status pending */ - - ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING; - - case 0: /* normal i/o interruption */ - - fctl = ioinfo[irq]->devstat.ii.irb.scsw.fctl; - stctl = ioinfo[irq]->devstat.ii.irb.scsw.stctl; - actl = ioinfo[irq]->devstat.ii.irb.scsw.actl; - - if ( chnchk && (ioinfo[irq]->senseid.cu_type == 0x3088)) - { - char buffer[80]; - - sprintf( buffer, "s390_process_IRQ(%04X) - irb for " - "device %04X after channel check\n", - irq, - ioinfo[irq]->devstat.devno ); - - s390_displayhex( buffer, - &(ioinfo[irq]->devstat.ii.irb) , - sizeof(irb_t)); - } /* endif */ - - ioinfo[irq]->stctl |= stctl; - - ending_status = ( stctl & SCSW_STCTL_SEC_STATUS ) - || ( stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND) ) - || ( (fctl == SCSW_FCTL_HALT_FUNC) && (stctl == SCSW_STCTL_STATUS_PEND) ); - - /* - * Check for unsolicited interrupts - for debug purposes only - * - * We only consider an interrupt as unsolicited, if the device was not - * actively in use (busy) and an interrupt other than an ALERT status - * was received. - * - * Note: We must not issue a message to the console, if the - * unsolicited interrupt applies to the console device - * itself ! - */ -#if CONFIG_DEBUG_IO - if ( ( irq != cons_dev ) - && !( stctl & SCSW_STCTL_ALERT_STATUS ) - && ( ioinfo[irq]->ui.flags.busy == 0 ) ) - { - char buffer[80]; - - printk( "Unsolicited interrupt received for device %04X on subchannel %04X\n" - " ... device status : %02X subchannel status : %02X\n", - ioinfo[irq]->devstat.devno, - irq, - ioinfo[irq]->devstat.dstat, - ioinfo[irq]->devstat.cstat); - - sprintf( buffer, "s390_process_IRQ(%04X) - irb for " - "device %04X, ending_status %d\n", - irq, - ioinfo[irq]->devstat.devno, - ending_status); - - s390_displayhex( buffer, - &(ioinfo[irq]->devstat.ii.irb) , - sizeof(irb_t)); - - } /* endif */ - - /* - * take fast exit if no handler is available - */ - if ( !action ) - return( ending_status ); - -#endif - /* - * Check whether we must issue a SENSE CCW ourselves if there is no - * concurrent sense facility installed for the subchannel. - * - * Note: We should check for ioinfo[irq]->ui.flags.consns but VM - * violates the ESA/390 architecture and doesn't present an - * operand exception for virtual devices without concurrent - * sense facility available/supported when enabling the - * concurrent sense facility. - */ - if ( ( ( ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK ) - && ( !issense ) ) - || ( ioinfo[irq]->ui.flags.delsense && ending_status ) ) - { - int ret_io; - ccw1_t *s_ccw = &ioinfo[irq]->senseccw; - unsigned long s_flag = 0; - - if ( ending_status ) - { - /* - * We copy the current status information into the device driver - * status area. Then we can use the local devstat area for device - * sensing. When finally calling the IRQ handler we must not overlay - * the original device status but copy the sense data only. - */ - memcpy( action->dev_id, - &(ioinfo[irq]->devstat), - sizeof( devstat_t) ); - - s_ccw->cmd_code = CCW_CMD_BASIC_SENSE; - s_ccw->cda = (__u32)virt_to_phys( ioinfo[irq]->devstat.ii.sense.data); - s_ccw->count = SENSE_MAX_COUNT; - s_ccw->flags = CCW_FLAG_SLI; - - /* - * If free_irq() or a sync do_IO/s390_start_IO() is in - * process we have to sense synchronously - */ - if ( ioinfo[irq]->ui.flags.unready || ioinfo[irq]->ui.flags.syncio ) - { - s_flag = DOIO_WAIT_FOR_INTERRUPT; - - } /* endif */ - - /* - * Reset status info - * - * It does not matter whether this is a sync. or async. - * SENSE request, but we have to assure we don't call - * the irq handler now, but keep the irq in busy state. - * In sync. mode s390_process_IRQ() is called recursively, - * while in async. mode we re-enter do_IRQ() with the - * next interrupt. - * - * Note : this may be a delayed sense request ! - */ - allow4handler = 0; - - ioinfo[irq]->ui.flags.fast = 0; - ioinfo[irq]->ui.flags.repall = 0; - ioinfo[irq]->ui.flags.w4final = 0; - ioinfo[irq]->ui.flags.delsense = 0; - - ioinfo[irq]->devstat.cstat = 0; - ioinfo[irq]->devstat.dstat = 0; - ioinfo[irq]->devstat.rescnt = SENSE_MAX_COUNT; - - ioinfo[irq]->ui.flags.w4sense = 1; - - ret_io = s390_start_IO( irq, - s_ccw, - 0xE2C5D5E2, // = SENSe - 0, // n/a - s_flag); - } - else - { - /* - * we received an Unit Check but we have no final - * status yet, therefore we must delay the SENSE - * processing. However, we must not report this - * intermediate status to the device interrupt - * handler. - */ - ioinfo[irq]->ui.flags.fast = 0; - ioinfo[irq]->ui.flags.repall = 0; - - ioinfo[irq]->ui.flags.delsense = 1; - allow4handler = 0; - - } /* endif */ - - } /* endif */ - - /* - * we allow for the device action handler if . - * - we received ending status - * - the action handler requested to see all interrupts - * - we received a PCI - * - fast notification was requested (primary status) - * - unsollicited interrupts - * - */ - if ( allow4handler ) - { - allow4handler = ending_status - || ( ioinfo[irq]->ui.flags.repall ) - || ( ioinfo[irq]->devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI ) - || ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) ) - || ( ioinfo[irq]->ui.flags.oper == 0 ); - - } /* endif */ - - /* - * We used to copy the device status information right before - * calling the device action handler. However, in status - * pending situations during do_IO() or halt_IO(), as well as - * enable_subchannel/disable_subchannel processing we must - * synchronously return the status information and must not - * call the device action handler. - * - */ - if ( allow4handler ) - { - /* - * if we were waiting for sense data we copy the sense - * bytes only as the original status information was - * saved prior to sense already. - */ - if ( ioinfo[irq]->ui.flags.w4sense ) - { - int sense_count = SENSE_MAX_COUNT-ioinfo[irq]->devstat.rescnt; - -#if CONFIG_DEBUG_IO - if ( irq != cons_dev ) - printk( "s390_process_IRQ( %04X ) : " - "BASIC SENSE bytes avail %d\n", - irq, sense_count ); -#endif - ioinfo[irq]->ui.flags.w4sense = 0; - ((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FLAG_SENSE_AVAIL; - ((devstat_t *)(action->dev_id))->scnt = sense_count; - - if ( sense_count >= 0 ) - { - memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data, - &(ioinfo[irq]->devstat.ii.sense.data), - sense_count); - } - else - { -#if 1 - panic( "s390_process_IRQ(%04x) encountered " - "negative sense count\n", - irq); -#else - printk( KERN_CRIT"s390_process_IRQ(%04x) encountered " - "negative sense count\n", - irq); -#endif - } /* endif */ - } - else - { - memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat ); - - } /* endif */ - - } /* endif */ - - /* - * for status pending situations other than deferred interrupt - * conditions detected by s390_process_IRQ() itself we must not - * call the handler. This will synchronously be reported back - * to the caller instead, e.g. when detected during do_IO(). - */ - if ( ioinfo[irq]->ui.flags.s_pend || ioinfo[irq]->ui.flags.unready ) - allow4handler = 0; - - /* - * Call device action handler if applicable - */ - if ( allow4handler ) - { - - /* - * We only reset the busy condition when we are sure that no further - * interrupt is pending for the current I/O request (ending_status). - */ - if ( ending_status || !ioinfo[irq]->ui.flags.oper ) - { - ioinfo[irq]->ui.flags.oper = 1; /* dev IS oper */ - - ioinfo[irq]->ui.flags.busy = 0; - ioinfo[irq]->ui.flags.doio = 0; - ioinfo[irq]->ui.flags.haltio = 0; - ioinfo[irq]->ui.flags.fast = 0; - ioinfo[irq]->ui.flags.repall = 0; - ioinfo[irq]->ui.flags.w4final = 0; - - ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; - ((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FINAL_STATUS; - - action->handler( irq, action->dev_id, ®s); - - // - // reset intparm after final status or we will badly present unsolicited - // interrupts with a intparm value possibly no longer valid. - // - ioinfo[irq]->devstat.intparm = 0; - - // - // Was there anything queued ? Start the pending channel program - // if there is one. - // - if ( ioinfo[irq]->ui.flags.doio_q ) - { - int ret; - - ret = s390_start_IO( irq, - ioinfo[irq]->qcpa, - ioinfo[irq]->qintparm, - ioinfo[irq]->qlpm, - ioinfo[irq]->qflag); - - ioinfo[irq]->ui.flags.doio_q = 0; - - /* - * If s390_start_IO() failed call the device's interrupt - * handler, the IRQ related devstat area was setup by - * s390_start_IO() accordingly already (status pending - * condition). - */ - if ( ret ) - { - action->handler( irq, action->dev_id, ®s); - - } /* endif */ - - } /* endif */ - - } - else - { - ioinfo[irq]->ui.flags.w4final = 1; - action->handler( irq, action->dev_id, ®s); - - } /* endif */ - - } /* endif */ - - break; - - case 3: /* device not operational */ - - ioinfo[irq]->ui.flags.oper = 0; - - ioinfo[irq]->ui.flags.busy = 0; - ioinfo[irq]->ui.flags.doio = 0; - ioinfo[irq]->ui.flags.haltio = 0; - - ioinfo[irq]->devstat.cstat = 0; - ioinfo[irq]->devstat.dstat = 0; - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS; - - /* - * When we find a device "not oper" we save the status - * information into the device status area and call the - * device specific interrupt handler. - * - * Note: currently we don't have any way to reenable - * the device unless an unsolicited interrupt - * is presented. We don't check for spurious - * interrupts on "not oper" conditions. - */ - - if ( ( ioinfo[irq]->ui.flags.fast ) - && ( ioinfo[irq]->ui.flags.w4final ) ) - { - /* - * If a new request was queued already, we have - * to simulate the "not oper" status for the - * queued request by switching the "intparm" value - * and notify the interrupt handler. - */ - if ( ioinfo[irq]->ui.flags.doio_q ) - { - ioinfo[irq]->devstat.intparm = ioinfo[irq]->qintparm; - - } /* endif */ - - } /* endif */ - - ioinfo[irq]->ui.flags.fast = 0; - ioinfo[irq]->ui.flags.repall = 0; - ioinfo[irq]->ui.flags.w4final = 0; - - memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat ); - - ioinfo[irq]->devstat.intparm = 0; - - if ( !ioinfo[irq]->ui.flags.s_pend ) - action->handler( irq, action->dev_id, ®s); - - ending_status = 1; - - break; - - } /* endswitch */ - - return( ending_status ); -} - -/* - * Set the special i/o-interruption sublass 7 for the - * device specified by parameter irq. There can only - * be a single device been operated on this special - * isc. This function is aimed being able to check - * on special device interrupts in disabled state, - * without having to delay I/O processing (by queueing) - * for non-console devices. - * - * Setting of this isc is done by set_cons_dev(), while - * reset_cons_dev() resets this isc and re-enables the - * default isc3 for this device. wait_cons_dev() allows - * to actively wait on an interrupt for this device in - * disabed state. When the interrupt condition is - * encountered, wait_cons_dev(9 calls do_IRQ() to have - * the console device driver processing the interrupt. - */ -int set_cons_dev( int irq ) -{ - int ccode; - unsigned long cr6 __attribute__ ((aligned (8))); - int rc = 0; - - if ( cons_dev != -1 ) - { - rc = -EBUSY; - } - else if ( (irq > highest_subchannel) || (irq < 0) ) - { - rc = -ENODEV; - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - else - { - /* - * modify the indicated console device to operate - * on special console interrupt sublass 7 - */ - ccode = stsch( irq, &(ioinfo[irq]->schib) ); - - if (ccode) - { - rc = -ENODEV; - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - } - else - { - ioinfo[irq]->schib.pmcw.isc = 7; - - ccode = msch( irq, &(ioinfo[irq]->schib) ); - - if (ccode) - { - rc = -EIO; - } - else - { - cons_dev = irq; - - /* - * enable console I/O-interrupt sublass 7 - */ - asm volatile ("STCTL 6,6,%0": "=m" (cr6)); - cr6 |= 0x01000000; - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - } /* endif */ - - } /* endif */ - - } /* endif */ - - return( rc); -} - -int reset_cons_dev( int irq) -{ - int rc = 0; - int ccode; - long cr6 __attribute__ ((aligned (8))); - - if ( cons_dev != -1 ) - { - rc = -EBUSY; - } - else if ( (irq > highest_subchannel) || (irq < 0) ) - { - rc = -ENODEV; - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - else - { - /* - * reset the indicated console device to operate - * on default console interrupt sublass 3 - */ - ccode = stsch( irq, &(ioinfo[irq]->schib) ); - - if (ccode) - { - rc = -ENODEV; - ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER; - } - else - { - - ioinfo[irq]->schib.pmcw.isc = 3; - - ccode = msch( irq, &(ioinfo[irq]->schib) ); - - if (ccode) - { - rc = -EIO; - } - else - { - cons_dev = -1; - - /* - * disable special console I/O-interrupt sublass 7 - */ - asm volatile ("STCTL 6,6,%0": "=m" (cr6)); - cr6 &= 0xFEFFFFFF; - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - } /* endif */ - - } /* endif */ - - } /* endif */ - - return( rc); -} - -int wait_cons_dev( int irq ) -{ - int rc = 0; - long save_cr6; - - if ( irq == cons_dev ) - { - - /* - * before entering the spinlock we may already have - * processed the interrupt on a different CPU ... - */ - if ( ioinfo[irq]->ui.flags.busy == 1 ) - { - long cr6 __attribute__ ((aligned (8))); - - /* - * disable all, but isc 7 (console device) - */ - asm volatile ("STCTL 6,6,%0": "=m" (cr6)); - save_cr6 = cr6; - cr6 &= 0x01FFFFFF; - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - do { - tpi_info_t tpi_info; - if (tpi(&tpi_info) == 1) { - s390_process_IRQ( tpi_info.irq ); - } else { - s390irq_spin_unlock(irq); - tod_wait(100); - s390irq_spin_lock(irq); - } - eieio(); - } while (ioinfo[irq]->ui.flags.busy == 1); - - /* - * restore previous isc value - */ - asm volatile ("STCTL 6,6,%0": "=m" (cr6)); - cr6 = save_cr6; - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - } /* endif */ - - } - else - { - rc = EINVAL; - - } /* endif */ - - - return(rc); -} - - -int enable_cpu_sync_isc( int irq ) -{ - int ccode; - long cr6 __attribute__ ((aligned (8))); - - int count = 0; - int rc = 0; - - if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA ) - { - ccode = stsch( irq, &(ioinfo[irq]->schib) ); - - if ( !ccode ) - { - ioinfo[irq]->schib.pmcw.isc = 5; - - do - { - ccode = msch( irq, &(ioinfo[irq]->schib) ); - - if (ccode == 0 ) - { - /* - * enable interrupt subclass in CPU - */ - asm volatile ("STCTL 6,6,%0": "=m" (cr6)); - cr6 |= 0x04000000; // enable sync isc 5 - cr6 &= 0xEFFFFFFF; // disable standard isc 3 - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - } - else if (ccode == 3) - { - rc = -ENODEV; // device not-oper - very unlikely - - } - else if (ccode == 2) - { - rc = -EBUSY; // device busy - should not happen - - } - else if (ccode == 1) - { - // - // process pending status - // - ioinfo[irq]->ui.flags.s_pend = 1; - - s390_process_IRQ( irq ); - - ioinfo[irq]->ui.flags.s_pend = 0; - - count++; - - } /* endif */ - - } while ( ccode == 1 && count < 3 ); - - if ( count == 3) - { - rc = -EIO; - - } /* endif */ - } - else - { - rc = -ENODEV; // device is not-operational - - } /* endif */ - } - else - { - rc = -EINVAL; - - } /* endif */ - - return( rc); -} - -int disable_cpu_sync_isc( int irq) -{ - int rc = 0; - int ccode; - long cr6 __attribute__ ((aligned (8))); - - if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA ) - { - ccode = stsch( irq, &(ioinfo[irq]->schib) ); - - ioinfo[irq]->schib.pmcw.isc = 3; - - ccode = msch( irq, &(ioinfo[irq]->schib) ); - - if (ccode) - { - rc = -EIO; - } - else - { - - /* - * enable interrupt subclass in CPU - */ - asm volatile ("STCTL 6,6,%0": "=m" (cr6)); - cr6 &= 0xFBFFFFFF; // disable sync isc 5 - cr6 |= 0x10000000; // enable standard isc 3 - asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory"); - - } /* endif */ - - } - else - { - rc = -EINVAL; - - } /* endif */ - - return( rc); -} - -// -// Input : -// devno - device number -// ps - pointer to sense ID data area -// -// Output : none -// -void VM_virtual_device_info( __u16 devno, - senseid_t *ps ) -{ - diag210_t diag_data; - int ccode; - - int error = 0; - - diag_data.vrdcdvno = devno; - diag_data.vrdclen = sizeof( diag210_t); - ccode = diag210( (diag210_t *)virt_to_phys( &diag_data ) ); - ps->reserved = 0xff; - - switch (diag_data.vrdcvcla) { - case 0x80: - - switch (diag_data.vrdcvtyp) { - case 00: - - ps->cu_type = 0x3215; - - break; - - default: - - error = 1; - - break; - - } /* endswitch */ - - break; - - case 0x40: - - switch (diag_data.vrdcvtyp) { - case 0xC0: - - ps->cu_type = 0x5080; - - break; - - case 0x80: - - ps->cu_type = 0x2250; - - break; - - case 0x04: - - ps->cu_type = 0x3277; - - break; - - case 0x01: - - ps->cu_type = 0x3278; - - break; - - default: - - error = 1; - - break; - - } /* endswitch */ - - break; - - case 0x20: - - switch (diag_data.vrdcvtyp) { - case 0x84: - - ps->cu_type = 0x3505; - - break; - - case 0x82: - - ps->cu_type = 0x2540; - - break; - - case 0x81: - - ps->cu_type = 0x2501; - - break; - - default: - - error = 1; - - break; - - } /* endswitch */ - - break; - - case 0x10: - - switch (diag_data.vrdcvtyp) { - case 0x84: - - ps->cu_type = 0x3525; - - break; - - case 0x82: - - ps->cu_type = 0x2540; - - break; - - case 0x4F: - case 0x4E: - case 0x48: - - ps->cu_type = 0x3820; - - break; - - case 0x4D: - case 0x49: - case 0x45: - - ps->cu_type = 0x3800; - - break; - - case 0x4B: - - ps->cu_type = 0x4248; - - break; - - case 0x4A: - - ps->cu_type = 0x4245; - - break; - - case 0x47: - - ps->cu_type = 0x3262; - - break; - - case 0x43: - - ps->cu_type = 0x3203; - - break; - - case 0x42: - - ps->cu_type = 0x3211; - - break; - - case 0x41: - - ps->cu_type = 0x1403; - - break; - - default: - - error = 1; - - break; - - } /* endswitch */ - - break; - - case 0x08: - - switch (diag_data.vrdcvtyp) { - case 0x82: - - ps->cu_type = 0x3422; - - break; - - case 0x81: - - ps->cu_type = 0x3490; - - break; - - case 0x10: - - ps->cu_type = 0x3420; - - break; - - case 0x02: - - ps->cu_type = 0x3430; - - break; - - case 0x01: - - ps->cu_type = 0x3480; - - break; - - case 0x42: - - ps->cu_type = 0x3424; - - break; - - case 0x44: - - ps->cu_type = 0x9348; - - break; - - default: - - error = 1; - - break; - - } /* endswitch */ - - break; - - default: - - error = 1; - - break; - - } /* endswitch */ - - if ( error ) - {printk( "DIAG X'210' for device %04X returned (cc = %d): vdev class : %02X, " - "vdev type : %04X \n ... rdev class : %02X, rdev type : %04X, rdev model: %02X\n", - devno, - ccode, - diag_data.vrdcvcla, - diag_data.vrdcvtyp, - diag_data.vrdcrccl, - diag_data.vrdccrty, - diag_data.vrdccrmd ); - - } /* endif */ - -} - -/* - * This routine returns the characteristics for the device - * specified. Some old devices might not provide the necessary - * command code information during SenseID processing. In this - * case the function returns -EINVAL. Otherwise the function - * allocates a decice specific data buffer and provides the - * device characteristics together with the buffer size. Its - * the callers responability to release the kernel memory if - * not longer needed. In case of persistent I/O problems -EBUSY - * is returned. - * - * The function may be called enabled or disabled. However, the - * caller must have locked the irq it is requesting data for. - * - * Note : It would have been nice to collect this information - * during init_IRQ() processing but this is not possible - * - * a) without statically pre-allocation fixed size buffers - * as virtual memory management isn't available yet. - * - * b) without unnecessarily increase system startup by - * evaluating devices eventually not used at all. - */ -int read_dev_chars( int irq, void **buffer, int length ) -{ - unsigned int flags; - ccw1_t *rdc_ccw; - devstat_t devstat; - char *rdc_buf; - int devflag; - - int ret = 0; - int emulated = 0; - int retry = 5; - - if ( !buffer || !length ) - { - return( -EINVAL ); - - } /* endif */ - - if ( (irq > highest_subchannel) || (irq < 0 ) ) - { - return( -ENODEV ); - - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - - if ( ioinfo[irq]->ui.flags.oper == 0 ) - { - return( -ENODEV ); - - } /* endif */ - - /* - * Before playing around with irq locks we should assure - * running disabled on (just) our CPU. Sync. I/O requests - * also require to run disabled. - * - * Note : as no global lock is required, we must not use - * cli(), but __cli() instead. - */ - __save_flags(flags); - __cli(); - - rdc_ccw = &ioinfo[irq]->senseccw; - - if ( !ioinfo[irq]->ui.flags.ready ) - { - ret = request_irq( irq, - init_IRQ_handler, - 0, "RDC", &devstat ); - - if ( !ret ) - { - emulated = 1; - - } /* endif */ - - } /* endif */ - - if ( !ret ) - { - if ( ! *buffer ) - { - rdc_buf = kmalloc( length, GFP_KERNEL); - } - else - { - rdc_buf = *buffer; - - } /* endif */ - - if ( !rdc_buf ) - { - ret = -ENOMEM; - } - else - { - do - { - rdc_ccw->cmd_code = CCW_CMD_RDC; - rdc_ccw->cda = (__u32)virt_to_phys( rdc_buf ); - rdc_ccw->count = length; - rdc_ccw->flags = CCW_FLAG_SLI; - - ret = s390_start_IO( irq, - rdc_ccw, - 0x00524443, // RDC - 0, // n/a - DOIO_WAIT_FOR_INTERRUPT ); - retry--; - devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag; - - } while ( ( retry ) - && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) ); - - } /* endif */ - - if ( !retry ) - { - ret = -EBUSY; - - } /* endif */ - - __restore_flags(flags); - - /* - * on success we update the user input parms - */ - if ( !ret ) - { - *buffer = rdc_buf; - - } /* endif */ - - if ( emulated ) - { - free_irq( irq, &devstat); - - } /* endif */ - - } /* endif */ - - return( ret ); -} - -/* - * Read Configuration data - */ -int read_conf_data( int irq, void **buffer, int *length ) -{ - int found = 0; - int ciw_cnt = 0; - unsigned int flags; - - int ret = 0; - - if ( (irq > highest_subchannel) || (irq < 0 ) ) - { - return( -ENODEV ); - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - - } /* endif */ - - if ( ioinfo[irq]->ui.flags.oper == 0 ) - { - return( -ENODEV ); - - } /* endif */ - - /* - * scan for RCD command in extended SenseID data - */ - for ( ; (found == 0) && (ciw_cnt < 62); ciw_cnt++ ) - { - if ( ioinfo[irq]->senseid.ciw[ciw_cnt].ct == CIW_TYPE_RCD ) - { - found = 1; - break; - } /* endif */ - - } /* endfor */ - - if ( found ) - { - ccw1_t *rcd_ccw = &ioinfo[irq]->senseccw; - devstat_t devstat; - char *rcd_buf; - int devflag; - - int emulated = 0; - int retry = 5; - - __save_flags(flags); - __cli(); - - if ( !ioinfo[irq]->ui.flags.ready ) - { - ret = request_irq( irq, - init_IRQ_handler, - 0, "RCD", &devstat ); - - if ( !ret ) - { - emulated = 1; - - } /* endif */ - - } /* endif */ - - if ( !ret ) - { - rcd_buf = kmalloc( ioinfo[irq]->senseid.ciw[ciw_cnt].count, - GFP_KERNEL); - - do - { - rcd_ccw->cmd_code = ioinfo[irq]->senseid.ciw[ciw_cnt].cmd; - rcd_ccw->cda = (__u32)virt_to_phys( rcd_buf ); - rcd_ccw->count = ioinfo[irq]->senseid.ciw[ciw_cnt].count; - rcd_ccw->flags = CCW_FLAG_SLI; - - ret = s390_start_IO( irq, - rcd_ccw, - 0x00524344, // == RCD - 0, // n/a - DOIO_WAIT_FOR_INTERRUPT ); - - retry--; - - devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag; - - } while ( ( retry ) - && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) ); - - if ( !retry ) - ret = -EBUSY; - - __restore_flags(flags); - - } /* endif */ - - /* - * on success we update the user input parms - */ - if ( !ret ) - { - *length = ioinfo[irq]->senseid.ciw[ciw_cnt].count; - *buffer = rcd_buf; - - } /* endif */ - - if ( emulated ) - free_irq( irq, &devstat); - } - else - { - ret = -EINVAL; - - } /* endif */ - - return( ret ); - -} - -int get_dev_info( int irq, dev_info_t * pdi) -{ - return( get_dev_info_by_irq( irq, pdi)); -} - -static int __inline__ get_next_available_irq( ioinfo_t *pi) -{ - int ret_val; - - while ( TRUE ) - { - if ( pi->ui.flags.oper ) - { - ret_val = pi->irq; - break; - } - else - { - pi = pi->next; - - // - // leave at end of list unconditionally - // - if ( pi == NULL ) - { - ret_val = -ENODEV; - break; - } - - } /* endif */ - - } /* endwhile */ - - return ret_val; -} - - -int get_irq_first( void ) -{ - int ret_irq; - - if ( ioinfo_head ) - { - if ( ioinfo_head->ui.flags.oper ) - { - ret_irq = ioinfo_head->irq; - } - else if ( ioinfo_head->next ) - { - ret_irq = get_next_available_irq( ioinfo_head->next ); - - } - else - { - ret_irq = -ENODEV; - - } /* endif */ - } - else - { - ret_irq = -ENODEV; - - } /* endif */ - - return ret_irq; -} - -int get_irq_next( int irq ) -{ - int ret_irq; - - if ( ioinfo[irq] != INVALID_STORAGE_AREA ) - { - if ( ioinfo[irq]->next ) - { - if ( ioinfo[irq]->next->ui.flags.oper ) - { - ret_irq = ioinfo[irq]->next->irq; - } - else - { - ret_irq = get_next_available_irq( ioinfo[irq]->next ); - - } /* endif */ - } - else - { - ret_irq = -ENODEV; - - } /* endif */ - } - else - { - ret_irq = -EINVAL; - - } /* endif */ - - return ret_irq; -} - -int get_dev_info_by_irq( int irq, dev_info_t *pdi) -{ - - if ( irq > highest_subchannel || irq < 0 ) - { - return -ENODEV; - } - else if ( pdi == NULL ) - { - return -EINVAL; - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } - else - { - pdi->devno = ioinfo[irq]->schib.pmcw.dev; - pdi->irq = irq; - - if ( ioinfo[irq]->ui.flags.oper ) - { - pdi->status = 0; - memcpy( &(pdi->sid_data), - &ioinfo[irq]->senseid, - sizeof( senseid_t)); - } - else - { - pdi->status = DEVSTAT_NOT_OPER; - memcpy( &(pdi->sid_data), - '\0', - sizeof( senseid_t)); - pdi->sid_data.cu_type = 0xFFFF; - - } /* endif */ - - if ( ioinfo[irq]->ui.flags.ready ) - pdi->status |= DEVSTAT_DEVICE_OWNED; - - return 0; - - } /* endif */ - -} - - -int get_dev_info_by_devno( __u16 devno, dev_info_t *pdi) -{ - int i; - int rc = -ENODEV; - - if ( devno > 0x0000ffff ) - { - return -ENODEV; - } - else if ( pdi == NULL ) - { - return -EINVAL; - } - else - { - - for ( i=0; i <= highest_subchannel; i++ ) - { - - if ( ioinfo[i] != INVALID_STORAGE_AREA - && ioinfo[i]->schib.pmcw.dev == devno ) - { - if ( ioinfo[i]->ui.flags.oper ) - { - pdi->status = 0; - pdi->irq = i; - pdi->devno = devno; - - memcpy( &(pdi->sid_data), - &ioinfo[i]->senseid, - sizeof( senseid_t)); - } - else - { - pdi->status = DEVSTAT_NOT_OPER; - pdi->irq = i; - pdi->devno = devno; - - memcpy( &(pdi->sid_data), '\0', sizeof( senseid_t)); - pdi->sid_data.cu_type = 0xFFFF; - - } /* endif */ - - if ( ioinfo[i]->ui.flags.ready ) - pdi->status |= DEVSTAT_DEVICE_OWNED; - - rc = 0; /* found */ - break; - - } /* endif */ - - } /* endfor */ - - return( rc); - - } /* endif */ - -} - -int get_irq_by_devno( __u16 devno ) -{ - int i; - int rc = -1; - - if ( devno <= 0x0000ffff ) - { - for ( i=0; i <= highest_subchannel; i++ ) - { - if ( (ioinfo[i] != INVALID_STORAGE_AREA ) - && (ioinfo[i]->schib.pmcw.dev == devno) - && (ioinfo[i]->schib.pmcw.dnv == 1 ) ) - { - rc = i; - break; - - } /* endif */ - - } /* endfor */ - - } /* endif */ - - return( rc); -} - -unsigned int get_devno_by_irq( int irq ) -{ - - if ( ( irq > highest_subchannel ) - || ( irq < 0 ) - || ( ioinfo[irq] == INVALID_STORAGE_AREA ) ) - { - return -1; - - } /* endif */ - - /* - * we don't need to check for the device be operational - * as the initial STSCH will always present the device - * number defined by the IOCDS regardless of the device - * existing or not. However, there could be subchannels - * defined who's device number isn't valid ... - */ - if ( ioinfo[irq]->schib.pmcw.dnv ) - return( ioinfo[irq]->schib.pmcw.dev ); - else - return -1; -} - -/* - * s390_device_recognition - * - * Used for system wide device recognition. Issues the device - * independant SenseID command to obtain info the device type. - * - */ -void s390_device_recognition( void) -{ - - int irq = 0; /* let's start with subchannel 0 ... */ - - do - { - /* - * We issue the SenseID command on I/O subchannels we think are - * operational only. - */ - if ( ( ioinfo[irq] != INVALID_STORAGE_AREA ) - && ( ioinfo[irq]->schib.pmcw.st == 0 ) - && ( ioinfo[irq]->ui.flags.oper == 1 ) ) - { - s390_SenseID( irq, &ioinfo[irq]->senseid ); - - } /* endif */ - - irq ++; - - } while ( irq <= highest_subchannel ); - -} - - -/* - * s390_search_devices - * - * Determines all subchannels available to the system. - * - */ -void s390_process_subchannels( void) -{ - int isValid; - int irq = 0; /* Evaluate all subchannels starting with 0 ... */ - - do - { - isValid = s390_validate_subchannel( irq); - - irq++; - - } while ( isValid && irq < __MAX_SUBCHANNELS ); - - highest_subchannel = --irq; - - printk( "\nHighest subchannel number detected: %u\n", - highest_subchannel); -} - -/* - * s390_validate_subchannel() - * - * Process the subchannel for the requested irq. Returns 1 for valid - * subchannels, otherwise 0. - */ -int s390_validate_subchannel( int irq ) -{ - - int retry; /* retry count for status pending conditions */ - int ccode; /* condition code for stsch() only */ - int ccode2; /* condition code for other I/O routines */ - schib_t *p_schib; - - /* - * The first subchannel that is not-operational (ccode==3) - * indicates that there aren't any more devices available. - */ - if ( ( init_IRQ_complete ) - && ( ioinfo[irq] != INVALID_STORAGE_AREA ) ) - { - p_schib = &ioinfo[irq]->schib; - } - else - { - p_schib = &init_schib; - - } /* endif */ - - ccode = stsch( irq, p_schib); - - if ( ccode == 0) - { - /* - * ... just being curious we check for non I/O subchannels - */ - if ( p_schib->pmcw.st ) - { - printk( "Subchannel %04X reports " - "non-I/O subchannel type %04X\n", - irq, - p_schib->pmcw.st); - - if ( ioinfo[irq] != INVALID_STORAGE_AREA ) - ioinfo[irq]->ui.flags.oper = 0; - - } /* endif */ - - if ( p_schib->pmcw.dnv ) - { - if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - - if ( !init_IRQ_complete ) - { - ioinfo[irq] = - (ioinfo_t *)alloc_bootmem( sizeof(ioinfo_t)); - } - else - { - ioinfo[irq] = - (ioinfo_t *)kmalloc( sizeof(ioinfo_t), - GFP_KERNEL ); - - } /* endif */ - - memset( ioinfo[irq], '\0', sizeof( ioinfo_t)); - memcpy( &ioinfo[irq]->schib, - &init_schib, - sizeof( schib_t)); - ioinfo[irq]->irq_desc.status = IRQ_DISABLED; - ioinfo[irq]->irq_desc.handler = &no_irq_type; - - /* - * We have to insert the new ioinfo element - * into the linked list, either at its head, - * its tail or insert it. - */ - if ( ioinfo_head == NULL ) /* first element */ - { - ioinfo_head = ioinfo[irq]; - ioinfo_tail = ioinfo[irq]; - } - else if ( irq < ioinfo_head->irq ) /* new head */ - { - ioinfo[irq]->next = ioinfo_head; - ioinfo_head->prev = ioinfo[irq]; - ioinfo_head = ioinfo[irq]; - } - else if ( irq > ioinfo_tail->irq ) /* new tail */ - { - ioinfo_tail->next = ioinfo[irq]; - ioinfo[irq]->prev = ioinfo_tail; - ioinfo_tail = ioinfo[irq]; - } - else /* insert element */ - { - ioinfo_t *pi = ioinfo_head; - - do - { - if ( irq < pi->next->irq ) - { - ioinfo[irq]->next = pi->next; - ioinfo[irq]->prev = pi; - pi->next->prev = ioinfo[irq]; - pi->next = ioinfo[irq]; - break; - - } /* endif */ - - pi = pi->next; - - } while ( 1 ); - - } /* endif */ - - } /* endif */ - - // initialize some values ... - ioinfo[irq]->ui.flags.pgid_supp = 1; - - ioinfo[irq]->opm = ioinfo[irq]->schib.pmcw.pam - & ioinfo[irq]->schib.pmcw.pom; - - printk( "Detected device %04X on subchannel %04X" - " - PIM = %02X, PAM = %02X, POM = %02X\n", - ioinfo[irq]->schib.pmcw.dev, - irq, - ioinfo[irq]->schib.pmcw.pim, - ioinfo[irq]->schib.pmcw.pam, - ioinfo[irq]->schib.pmcw.pom); - - /* - * We should have at least one CHPID ... - */ - if ( ioinfo[irq]->schib.pmcw.pim - & ioinfo[irq]->schib.pmcw.pam - & ioinfo[irq]->schib.pmcw.pom ) - { - ioinfo[irq]->ui.flags.oper = 0; - - /* - * We now have to initially ... - * ... set "interruption sublass" - * ... enable "concurrent sense" - * ... enable "multipath mode" if more than one - * CHPID is available. This is done regardless - * whether multiple paths are available for us. - * - * Note : we don't enable the device here, this is temporarily - * done during device sensing below. - */ - ioinfo[irq]->schib.pmcw.isc = 3; /* could be smth. else */ - ioinfo[irq]->schib.pmcw.csense = 1; /* concurrent sense */ - ioinfo[irq]->schib.pmcw.ena = 0; /* force disable it */ - ioinfo[irq]->schib.pmcw.intparm = - ioinfo[irq]->schib.pmcw.dev; - - if ( ( ioinfo[irq]->schib.pmcw.pim != 0 ) - && ( ioinfo[irq]->schib.pmcw.pim != 0x80 ) ) - { - ioinfo[irq]->schib.pmcw.mp = 1; /* multipath mode */ - - } /* endif */ - - /* - * initialize ioinfo structure - */ - ioinfo[irq]->irq = irq; - ioinfo[irq]->ui.flags.busy = 0; - ioinfo[irq]->ui.flags.ready = 0; - ioinfo[irq]->ui.flags.oper = 1; - ioinfo[irq]->devstat.intparm = 0; - ioinfo[irq]->devstat.devno = ioinfo[irq]->schib.pmcw.dev; - - retry = 5; - - do - { - ccode2 = msch_err( irq, &ioinfo[irq]->schib); - - switch (ccode2) { - case 0: // successful completion - // - // concurrent sense facility available ... - // - ioinfo[irq]->ui.flags.consns = 1; - break; - - case 1: // status pending - // - // How can we have a pending status as device is - // disabled for interrupts ? Anyway, clear it ... - // - tsch( irq, &(ioinfo[irq]->devstat.ii.irb) ); - retry--; - break; - - case 2: // busy - retry--; - break; - - case 3: // not operational - ioinfo[irq]->ui.flags.oper = 0; - retry = 0; - break; - - default: -#define PGMCHK_OPERAND_EXC 0x15 - - if ( (ccode2 & PGMCHK_OPERAND_EXC) == PGMCHK_OPERAND_EXC ) - { - /* - * re-issue the modify subchannel without trying to - * enable the concurrent sense facility - */ - ioinfo[irq]->schib.pmcw.csense = 0; - - ccode2 = msch_err( irq, &ioinfo[irq]->schib); - - if ( ccode2 != 0 ) - { - printk( " ... modify subchannel (2) failed with CC = %X\n", - ccode2 ); - ioinfo[irq]->ui.flags.oper = 0; - } - else - { - ioinfo[irq]->ui.flags.consns = 0; - - } /* endif */ - } - else - { - printk( " ... modify subchannel (1) failed with CC = %X\n", - ccode2); - ioinfo[irq]->ui.flags.oper = 0; - - } /* endif */ - - retry = 0; - break; - - } /* endswitch */ - - } while ( ccode2 && retry ); - - if ( (ccode2 < 3) && (!retry) ) - { - printk( " ... msch() retry count for " - "subchannel %04X exceeded, CC = %d\n", - irq, - ccode2); - - } /* endif */ - - } - else - { - ioinfo[irq]->ui.flags.oper = 0; - - } /* endif */ - - } /* endif */ - - } /* endif */ - - /* - * indicate whether the subchannel is valid - */ - if ( ccode == 3) - return(0); - else - return(1); -} - -/* - * s390_SenseID - * - * Try to obtain the 'control unit'/'device type' information - * associated with the subchannel. - * - * The function is primarily meant to be called without irq - * action handler in place. However, it also allows for - * use with an action handler in place. If there is already - * an action handler registered assure it can handle the - * s390_SenseID() related device interrupts - interruption - * parameter used is 0x00E2C9C4 ( SID ). - */ -int s390_SenseID( int irq, senseid_t *sid ) -{ - ccw1_t sense_ccw; /* ccw area for SenseID command */ - devstat_t devstat; /* required by request_irq() */ - - int irq_ret = 0; /* return code */ - int retry = 5; /* retry count */ - int inlreq = 0; /* inline request_irq() */ - - if ( (irq > highest_subchannel) || (irq < 0 ) ) - { - return( -ENODEV ); - - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - } /* endif */ - - if ( ioinfo[irq]->ui.flags.oper == 0 ) - { - return( -ENODEV ); - - } /* endif */ - - if ( !ioinfo[irq]->ui.flags.ready ) - { - /* - * Perform SENSE ID command processing. We have to request device - * ownership and provide a dummy I/O handler. We issue sync. I/O - * requests and evaluate the devstat area on return therefore - * we don't need a real I/O handler in place. - */ - irq_ret = request_irq( irq, init_IRQ_handler, 0, "SID", &devstat); - - if ( irq_ret == 0 ) - inlreq = 1; - - } /* endif */ - - if ( irq_ret == 0 ) - { - s390irq_spin_lock( irq); - - sense_ccw.cmd_code = CCW_CMD_SENSE_ID; - sense_ccw.cda = (__u32)virt_to_phys( sid ); - sense_ccw.count = sizeof( senseid_t); - sense_ccw.flags = CCW_FLAG_SLI; - - ioinfo[irq]->senseid.cu_type = 0xFFFF; /* initialize fields ... */ - ioinfo[irq]->senseid.cu_model = 0; - ioinfo[irq]->senseid.dev_type = 0; - ioinfo[irq]->senseid.dev_model = 0; - - /* - * We now issue a SenseID request. In case of BUSY - * or STATUS PENDING conditions we retry 5 times. - */ - do - { - memset( &devstat, '\0', sizeof( devstat_t) ); - - irq_ret = s390_start_IO( irq, - &sense_ccw, - 0x00E2C9C4, // == SID - 0, // n/a - DOIO_WAIT_FOR_INTERRUPT - | DOIO_TIMEOUT ); - - if ( irq_ret == -ETIMEDOUT ) - { - halt_IO( irq, - 0x80E2C9C4, - DOIO_WAIT_FOR_INTERRUPT); - devstat.flag |= DEVSTAT_NOT_OPER; - - } /* endif */ - - if ( sid->cu_type == 0xFFFF && devstat.flag != DEVSTAT_NOT_OPER ) - { - if ( devstat.flag & DEVSTAT_STATUS_PENDING ) - { -#if CONFIG_DEBUG_IO - printk( "Device %04X on Subchannel %04X " - "reports pending status, retry : %d\n", - ioinfo[irq]->schib.pmcw.dev, - irq, - retry); -#endif - } /* endif */ - - if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL ) - { - /* - * if the device doesn't support the SenseID - * command further retries wouldn't help ... - */ - if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT ) - { - retry = 0; - } -#if CONFIG_DEBUG_IO - else - { - printk( "Device %04X," - " UC/SenseID," - " retry %d, cnt %02d," - " sns :" - " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - ioinfo[irq]->schib.pmcw.dev, - retry, - devstat.scnt, - devstat.ii.sense.data[0], - devstat.ii.sense.data[1], - devstat.ii.sense.data[2], - devstat.ii.sense.data[3], - devstat.ii.sense.data[4], - devstat.ii.sense.data[5], - devstat.ii.sense.data[6], - devstat.ii.sense.data[7]); - - } /* endif */ -#endif - } - else if ( devstat.flag & DEVSTAT_NOT_OPER ) - { - printk( "Device %04X on Subchannel %04X " - "became 'not operational'\n", - ioinfo[irq]->schib.pmcw.dev, - irq); - - retry = 0; - - } /* endif */ - } - else // we got it or the device is not-operational ... - { - retry = 0; - - } /* endif */ - - retry--; - - } while ( retry > 0 ); - - s390irq_spin_unlock( irq); - - /* - * If we installed the irq action handler we have to - * release it too. - */ - if ( inlreq ) - free_irq( irq, &devstat); - - /* - * if running under VM check there ... perhaps we should do - * only if we suffered a command reject, but it doesn't harm - */ - if ( ( sid->cu_type == 0xFFFF ) - && ( MACHINE_IS_VM ) ) - { - VM_virtual_device_info( ioinfo[irq]->schib.pmcw.dev, - sid ); - } /* endif */ - - if ( sid->cu_type == 0xFFFF ) - { - /* - * SenseID CU-type of 0xffff indicates that no device - * information could be retrieved (pre-init value). - * - * If we can't couldn't identify the device type we - * consider the device "not operational". - */ - printk( "Unknown device %04X on subchannel %04X\n", - ioinfo[irq]->schib.pmcw.dev, - irq); - ioinfo[irq]->ui.flags.oper = 0; - - } /* endif */ - - /* - * Issue device info message if unit was operational . - */ - if ( ioinfo[irq]->ui.flags.oper ) - { - if ( sid->dev_type != 0 ) - { - printk( "Device %04X reports: CU Type/Mod = %04X/%02X," - " Dev Type/Mod = %04X/%02X\n", - ioinfo[irq]->schib.pmcw.dev, - sid->cu_type, - sid->cu_model, - sid->dev_type, - sid->dev_model); - } - else - { - printk( "Device %04X reports:" - " Dev Type/Mod = %04X/%02X\n", - ioinfo[irq]->schib.pmcw.dev, - sid->cu_type, - sid->cu_model); - - } /* endif */ - - } /* endif */ - - if ( ioinfo[irq]->ui.flags.oper ) - irq_ret = 0; - else - irq_ret = -ENODEV; - - } /* endif */ - - return( irq_ret ); -} - -static int __inline__ s390_SetMultiPath( int irq ) -{ - int cc; - - cc = stsch( irq, &ioinfo[irq]->schib ); - - if ( !cc ) - { - ioinfo[irq]->schib.pmcw.mp = 1; /* multipath mode */ - - cc = msch( irq, &ioinfo[irq]->schib ); - - } /* endif */ - - return( cc); -} - -/* - * Device Path Verification - * - * Path verification is accomplished by checking which paths (CHPIDs) are - * available. Further, a path group ID is set, if possible in multipath - * mode, otherwise in single path mode. - * - */ -int s390_DevicePathVerification( int irq ) -{ -#if 0 - int ccode; - __u8 pathmask; - - int ret = 0; - - if ( ioinfo[irq]->ui.flags.pgid_supp == 0 ) - { - ret = -EOPNOTSUPP; - - } /* endif */ - - ccode = stsch( irq, &(ioinfo[irq]->schib) ); - - if ( ccode ) - { - ret = -ENODEV; - } - else - { - int i; - pgid_t pgid; - - int first = 1; - __u8 dev_path = ioinfo[irq]->schib.pmcw.pam - & ioinfo[irq]->schib.pmcw.pom; - - /* - * let's build a path group ID if we don't have one yet - */ - if ( ioinfo[irq]->ui.flags.pgid == 0) - { - struct _lowcore *lowcore = &get_cpu_lowcore(cpu); - - ioinfo->pgid.cpu_addr = lowcore->cpu_data.cpu_addr; - ioinfo->pgid.cpu_id = lowcore->cpu_data.cpu_id.ident; - ioinfo->pgid.cpu_model = lowcore->cpu_data.cpu_id.machine; - ioinfo->pgid.tod_high = *(__u32 *)&irq_IPL_TOD; - - ioinfo[irq]->ui.flags.pgid = 1; - - } /* endif */ - - memcpy( &pgid, ioinfo[irq]->pgid, sizeof(pgid_t)); - - for ( i = 0; i < 8 && !ret ; i++) - { - pathmask = 0x80 >> i; - - if ( dev_path & pathmask ) - { - ret = s390_SetPGID( irq, pathmask, &pgid ); - - /* - * For the *first* path we are prepared - * for recovery - * - * - If we fail setting the PGID we assume its - * using a different PGID already (VM) we - * try to sense. - */ - if ( ret == -EOPNOTSUPP && first ) - { - *(int *)&pgid = 0; - - ret = s390_SensePGID( irq, pathmask, &pgid); - first = 0; - - if ( !ret ) - { - /* - * Check whether we retrieved - * a reasonable PGID ... - */ - if ( !ret && (*(int *)&pgid == 0) ) - { - ret = -EOPNOTSUPP; - } - else - { - ret = s390_SetPGID( irq, pathmask, &pgid ); - - } /* endif */ - - } /* endif */ - - if ( ret ) - { - ioinfo[irq]->ui.flags.pgid_supp = 0; - - printk( "PathVerification(%04X) " - "- Device %04X doesn't " - " support path grouping", - irq, - ioinfo[irq]->schib.pmcw.dev); - - } /* endif */ - } - else if ( ret ) - { - ioinfo[irq]->ui.flags.pgid_supp = 0; - - } /* endif */ - - } /* endif */ - - } /* endfor */ - - } /* endif */ - - return ret; -#else - return 0; -#endif -} - -/* - * s390_SetPGID - * - * Set Path Group ID - * - */ -int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid ) -{ - ccw1_t spid_ccw; /* ccw area for SPID command */ - devstat_t devstat; /* required by request_irq() */ - - int irq_ret = 0; /* return code */ - int retry = 5; /* retry count */ - int inlreq = 0; /* inline request_irq() */ - int mpath = 1; /* try multi-path first */ - - if ( (irq > highest_subchannel) || (irq < 0 ) ) - { - return( -ENODEV ); - - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - - } /* endif */ - - if ( ioinfo[irq]->ui.flags.oper == 0 ) - { - return( -ENODEV ); - - } /* endif */ - - if ( !ioinfo[irq]->ui.flags.ready ) - { - /* - * Perform SENSE ID command processing. We have to request device - * ownership and provide a dummy I/O handler. We issue sync. I/O - * requests and evaluate the devstat area on return therefore - * we don't need a real I/O handler in place. - */ - irq_ret = request_irq( irq, init_IRQ_handler, 0, "SPID", &devstat); - - if ( irq_ret == 0 ) - inlreq = 1; - - } /* endif */ - - if ( irq_ret == 0 ) - { - s390irq_spin_lock( irq); - - spid_ccw.cmd_code = CCW_CMD_SET_PGID; - spid_ccw.cda = (__u32)virt_to_phys( pgid ); - spid_ccw.count = sizeof( pgid_t); - spid_ccw.flags = CCW_FLAG_SLI; - - - /* - * We now issue a SenseID request. In case of BUSY - * or STATUS PENDING conditions we retry 5 times. - */ - do - { - memset( &devstat, '\0', sizeof( devstat_t) ); - - irq_ret = s390_start_IO( irq, - &spid_ccw, - 0xE2D7C9C4, // == SPID - lpm, // n/a - DOIO_WAIT_FOR_INTERRUPT - | DOIO_VALID_LPM ); - - if ( !irq_ret ) - { - if ( devstat.flag & DEVSTAT_STATUS_PENDING ) - { -#if CONFIG_DEBUG_IO - printk( "SPID - Device %04X " - "on Subchannel %04X " - "reports pending status, " - "retry : %d\n", - ioinfo[irq]->schib.pmcw.dev, - irq, - retry); -#endif - } /* endif */ - - if ( devstat.flag == ( DEVSTAT_START_FUNCTION - | DEVSTAT_FINAL_STATUS ) ) - { - retry = 0; // successfully set ... - } - else if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL ) - { - /* - * If the device doesn't support the - * Sense Path Group ID command - * further retries wouldn't help ... - */ - if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT ) - { - if ( mpath ) - { - pgid->inf.fc = SPID_FUNC_ESTABLISH; - mpath = 0; - retry--; - } - else - { - irq_ret = -EOPNOTSUPP; - retry = 0; - - } /* endif */ - } -#if CONFIG_DEBUG_IO - else - { - printk( "SPID - device %04X," - " unit check," - " retry %d, cnt %02d," - " sns :" - " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - ioinfo[irq]->schib.pmcw.dev, - retry, - devstat.scnt, - devstat.ii.sense.data[0], - devstat.ii.sense.data[1], - devstat.ii.sense.data[2], - devstat.ii.sense.data[3], - devstat.ii.sense.data[4], - devstat.ii.sense.data[5], - devstat.ii.sense.data[6], - devstat.ii.sense.data[7]); - - } /* endif */ -#endif - } - else if ( devstat.flag & DEVSTAT_NOT_OPER ) - { - printk( "SPID - Device %04X " - "on Subchannel %04X " - "became 'not operational'\n", - ioinfo[irq]->schib.pmcw.dev, - irq); - - retry = 0; - - } /* endif */ - } - else if ( irq_ret != -ENODEV ) - { - retry--; - } - else - { - retry = 0; - - } /* endif */ - - } while ( retry > 0 ); - - s390irq_spin_unlock( irq); - - /* - * If we installed the irq action handler we have to - * release it too. - */ - if ( inlreq ) - free_irq( irq, &devstat); - - } /* endif */ - - return( irq_ret ); -} - - -/* - * s390_SensePGID - * - * Sense Path Group ID - * - */ -int s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid ) -{ - ccw1_t snid_ccw; /* ccw area for SNID command */ - devstat_t devstat; /* required by request_irq() */ - - int irq_ret = 0; /* return code */ - int retry = 5; /* retry count */ - int inlreq = 0; /* inline request_irq() */ - - if ( (irq > highest_subchannel) || (irq < 0 ) ) - { - return( -ENODEV ); - - } - else if ( ioinfo[irq] == INVALID_STORAGE_AREA ) - { - return( -ENODEV); - - } /* endif */ - - if ( ioinfo[irq]->ui.flags.oper == 0 ) - { - return( -ENODEV ); - - } /* endif */ - - if ( !ioinfo[irq]->ui.flags.ready ) - { - /* - * Perform SENSE ID command processing. We have to request device - * ownership and provide a dummy I/O handler. We issue sync. I/O - * requests and evaluate the devstat area on return therefore - * we don't need a real I/O handler in place. - */ - irq_ret = request_irq( irq, init_IRQ_handler, 0, "SNID", &devstat); - - if ( irq_ret == 0 ) - inlreq = 1; - - } /* endif */ - - if ( irq_ret == 0 ) - { - s390irq_spin_lock( irq); - - snid_ccw.cmd_code = CCW_CMD_SENSE_PGID; - snid_ccw.cda = (__u32)virt_to_phys( pgid ); - snid_ccw.count = sizeof( pgid_t); - snid_ccw.flags = CCW_FLAG_SLI; - - /* - * We now issue a SenseID request. In case of BUSY - * or STATUS PENDING conditions we retry 5 times. - */ - do - { - memset( &devstat, '\0', sizeof( devstat_t) ); - - irq_ret = s390_start_IO( irq, - &snid_ccw, - 0xE2D5C9C4, // == SNID - lpm, // n/a - DOIO_WAIT_FOR_INTERRUPT - | DOIO_VALID_LPM ); - - if ( !irq_ret ) - { - if ( devstat.flag & DEVSTAT_STATUS_PENDING ) - { -#if CONFIG_DEBUG_IO - printk( "SNID - Device %04X " - "on Subchannel %04X " - "reports pending status, " - "retry : %d\n", - ioinfo[irq]->schib.pmcw.dev, - irq, - retry); -#endif - } /* endif */ - - if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL ) - { - /* - * If the device doesn't support the - * Sense Path Group ID command - * further retries wouldn't help ... - */ - if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT ) - { - retry = 0; - irq_ret = -EOPNOTSUPP; - } -#if CONFIG_DEBUG_IO - else - { - printk( "SNID - device %04X," - " unit check," - " retry %d, cnt %02d," - " sns :" - " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - ioinfo[irq]->schib.pmcw.dev, - retry, - devstat.scnt, - devstat.ii.sense.data[0], - devstat.ii.sense.data[1], - devstat.ii.sense.data[2], - devstat.ii.sense.data[3], - devstat.ii.sense.data[4], - devstat.ii.sense.data[5], - devstat.ii.sense.data[6], - devstat.ii.sense.data[7]); - - } /* endif */ -#endif - } - else if ( devstat.flag & DEVSTAT_NOT_OPER ) - { - printk( "SNID - Device %04X " - "on Subchannel %04X " - "became 'not operational'\n", - ioinfo[irq]->schib.pmcw.dev, - irq); - - retry = 0; - - } /* endif */ - } - else if ( irq_ret != -ENODEV ) - { - retry--; - } - else - { - retry = 0; - - } /* endif */ - - } while ( retry > 0 ); - - s390irq_spin_unlock( irq); - - /* - * If we installed the irq action handler we have to - * release it too. - */ - if ( inlreq ) - free_irq( irq, &devstat); - - } /* endif */ - - return( irq_ret ); -} - - -void do_crw_pending( void ) -{ - return; -} - - -/* added by Holger Smolinski for reipl support in reipl.S */ -void -reipl ( int sch ) -{ - int i; - - for ( i = 0; i < highest_subchannel; i ++ ) { - free_irq ( i, (void*)REIPL_DEVID_MAGIC ); - } - do_reipl( 0x10000 | sch ); -} - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/s390mach.c linux.ac/arch/s390/kernel/s390mach.c --- linux-2.4.0/arch/s390/kernel/s390mach.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/s390mach.c Thu Jan 1 01:00:00 1970 @@ -1,157 +0,0 @@ -/* - * arch/s390/kernel/s390mach.c - * S/390 machine check handler, - * currently only channel-reports are supported - * - * S390 version - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Ingo Adlung (adlung@de.ibm.com) - */ - -#include - -#include -#include -#include -#include -#include -#include - -#define S390_MACHCHK_DEBUG - -static mchchk_queue_element_t *mchchk_queue_head = NULL; -static mchchk_queue_element_t *mchchk_queue_tail = NULL; -static mchchk_queue_element_t *mchchk_queue_free = NULL; -static spinlock_t mchchk_queue_lock; -static struct semaphore s_sem[2]; - -// -// initialize machine check handling -// -void s390_init_machine_check( void ) -{ - init_MUTEX_LOCKED( &s_sem[0] ); - init_MUTEX_LOCKED( &s_sem[1] ); - -#if 0 - // - // fix me ! initialize a machine check queue with 100 elements - // -#ifdef S390_MACHCHK_DEBUG - printk( "init_mach : starting kernel thread\n"); -#endif - - kernel_thread( s390_machine_check_handler, s_sem, 0); - - // - // wait for the machine check handler to be ready - // -#ifdef S390_MACHCHK_DEBUG - printk( "init_mach : waiting for kernel thread\n"); -#endif - - down( &sem[0]); - -#ifdef S390_MACHCHK_DEBUG - printk( "init_mach : kernel thread ready\n"); -#endif - - // - // fix me ! we have to initialize CR14 to allow for CRW pending - // conditions - - // - // fix me ! enable machine checks in the PSW - // -#endif - return; -} - -// -// machine check pre-processor -// -void __init s390_do_machine_check( void ) -{ - // fix me ! we have to check for machine check and - // post the handler eventually - - return; -} - -// -// machine check handler -// -static void __init s390_machine_check_handler( struct semaphore *sem ) -{ -#ifdef S390_MACHCHK_DEBUG - printk( "mach_handler : kernel thread up\n"); -#endif - - up( &sem[0] ); - -#ifdef S390_MACHCHK_DEBUG - printk( "mach_handler : kernel thread ready\n"); -#endif - - do { - -#ifdef S390_MACHCHK_DEBUG - printk( "mach_handler : waiting for wakeup\n"); -#endif - - down_interruptible( &sem[1] ); -#ifdef S390_MACHCHK_DEBUG - printk( "mach_handler : wakeup\n"); -#endif - - break; // fix me ! unconditional surrender ... - - // fix me ! check for machine checks and - // call do_crw_pending() eventually - - } while (1); - - return; -} - -mchchk_queue_element_t *s390_get_mchchk( void ) -{ - unsigned long flags; - mchchk_queue_element_t *qe; - - spin_lock_irqsave( &mchchk_queue_lock, flags ); - - // fix me ! dequeue first element if available - qe = NULL; - - spin_unlock_irqrestore( &mchchk_queue_lock, flags ); - - return qe; -} - -void s390_free_mchchk( mchchk_queue_element_t *mchchk ) -{ - unsigned long flags; - - if ( mchchk != NULL) - { - spin_lock_irqsave( &mchchk_queue_lock, flags ); - - mchchk->next = mchchk_queue_free; - - if ( mchchk_queue_free != NULL ) - { - mchchk_queue_free->prev = mchchk; - - } /* endif */ - - mchchk->prev = NULL; - mchchk_queue_free = mchchk; - - spin_unlock_irqrestore( &mchchk_queue_lock, flags ); - - } /* endif */ - - return; -} - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/semaphore.c linux.ac/arch/s390/kernel/semaphore.c --- linux-2.4.0/arch/s390/kernel/semaphore.c Sun Nov 12 03:02:40 2000 +++ linux.ac/arch/s390/kernel/semaphore.c Fri Jan 5 00:00:32 2001 @@ -2,7 +2,7 @@ * linux/arch/S390/kernel/semaphore.c * * S390 version - * Copyright (C) 1998 IBM Corporation + * Copyright (C) 1998-2000 IBM Corporation * Author(s): Martin Schwidefsky * * Derived from "linux/arch/i386/kernel/semaphore.c diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/setup.c linux.ac/arch/s390/kernel/setup.c --- linux-2.4.0/arch/s390/kernel/setup.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/setup.c Fri Jan 5 00:00:32 2001 @@ -45,6 +45,7 @@ __u16 boot_cpu_addr; int cpus_initialized = 0; unsigned long cpu_initialized = 0; +volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ /* * Setup options @@ -80,6 +81,7 @@ void __init cpu_init (void) { int nr = smp_processor_id(); + int addr = hard_smp_processor_id(); if (test_and_set_bit(nr,&cpu_initialized)) { printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr); @@ -91,7 +93,7 @@ * Store processor id in lowcore (used e.g. in timer_interrupt) */ asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id)); - S390_lowcore.cpu_data.cpu_addr = hard_smp_processor_id(); + S390_lowcore.cpu_data.cpu_addr = addr; S390_lowcore.cpu_data.cpu_nr = nr; /* @@ -158,33 +160,18 @@ { if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) cpcmd(vmhalt_cmd, NULL, 0); - disabled_wait(0); + signal_processor(smp_processor_id(), sigp_stop_and_store_status); } void machine_power_off(void) { if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) cpcmd(vmpoff_cmd, NULL, 0); - disabled_wait(0); + signal_processor(smp_processor_id(), sigp_stop_and_store_status); } #endif /* - * Waits for 'delay' microseconds using the tod clock - */ -void tod_wait(unsigned long delay) -{ - uint64_t start_cc, end_cc; - - if (delay == 0) - return; - asm volatile ("STCK %0" : "=m" (start_cc)); - do { - asm volatile ("STCK %0" : "=m" (end_cc)); - } while (((end_cc - start_cc)/4096) < delay); -} - -/* * Setup function called from init/main.c just after the banner * was printed. */ @@ -192,12 +179,11 @@ { unsigned long bootmap_size; unsigned long memory_start, memory_end; - char c = ' ', *to = command_line, *from = COMMAND_LINE; + char c = ' ', cn, *to = command_line, *from = COMMAND_LINE; struct resource *res; unsigned long start_pfn, end_pfn; static unsigned int smptrap=0; unsigned long delay = 0; - int len = 0; if (smptrap) return; @@ -210,6 +196,7 @@ */ cpu_init(); boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; + __cpu_logical_map[0] = boot_cpu_addr; /* * print what head.S has found out about the machine @@ -227,10 +214,15 @@ rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); #endif - /* nasty stuff with PARMAREAs. we use head.S or parameterline - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; - */ + memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/ + memory_end = MEMORY_SIZE; + /* + * We need some free virtual space to be able to do vmalloc. + * On a machine with 2GB memory we make sure that we have at + * least 128 MB free space for vmalloc. + */ + if (memory_end > 1920*1024*1024) + memory_end = 1920*1024*1024; memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/ memory_end = MEMORY_SIZE; /* detected in head.s */ init_mm.start_code = PAGE_OFFSET; @@ -252,7 +244,6 @@ * "mem=XXX[kKmM]" sets memsize */ if (c == ' ' && strncmp(from, "mem=", 4) == 0) { - if (to != command_line) to--; memory_end = simple_strtoul(from+4, &from, 0); if ( *from == 'K' || *from == 'k' ) { memory_end = memory_end << 10; @@ -275,16 +266,22 @@ delay = delay*60*1000000; from++; } - /* now wait for the requestion amount of time */ - tod_wait(delay); + /* now wait for the requestedn amount of time */ + udelay(delay); } - c = *(from++); - if (!c) + cn = *(from++); + if (!cn) break; - if (COMMAND_LINE_SIZE <= ++len) + if (cn == '\n') + cn = ' '; /* replace newlines with space */ + if (cn == ' ' && c == ' ') + continue; /* remove additional spaces */ + c = cn; + if (to - command_line >= COMMAND_LINE_SIZE) break; *(to++) = c; } + if (c == ' ' && to > command_line) to--; *to = '\0'; *cmdline_p = command_line; @@ -317,7 +314,7 @@ paging_init(); #ifdef CONFIG_BLK_DEV_INITRD if (INITRD_START) { - if (INITRD_START + INITRD_SIZE < memory_end) { + if (INITRD_START + INITRD_SIZE <= memory_end) { reserve_bootmem(INITRD_START, INITRD_SIZE); initrd_start = INITRD_START; initrd_end = initrd_start + INITRD_SIZE; @@ -368,8 +365,8 @@ p += sprintf(p,"vendor_id : IBM/S390\n" "# processors : %i\n" "bogomips per cpu: %lu.%02lu\n", - smp_num_cpus, loops_per_sec/500000, - (loops_per_sec/5000)%100); + smp_num_cpus, loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ))%100); for (i = 0; i < smp_num_cpus; i++) { cpuinfo = &safe_get_cpu_lowcore(i).cpu_data; p += sprintf(p,"processor %i: " diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/signal.c linux.ac/arch/s390/kernel/signal.c --- linux-2.4.0/arch/s390/kernel/signal.c Sun Sep 3 19:53:42 2000 +++ linux.ac/arch/s390/kernel/signal.c Fri Jan 5 00:00:32 2001 @@ -2,7 +2,7 @@ * arch/s390/kernel/signal.c * * S390 version - * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * * Based on Intel version @@ -12,6 +12,8 @@ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson */ +#include + #include #include #include @@ -37,7 +39,7 @@ #define SIGFRAME_COMMON \ __u8 callee_used_stack[__SIGNAL_FRAMESIZE]; \ struct sigcontext sc; \ -sigregs sregs; \ +_sigregs sregs; \ __u8 retcode[S390_SYSCALL_SIZE]; typedef struct @@ -56,6 +58,41 @@ int options, unsigned long *ru); asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); +int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) +{ + if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) + return -EFAULT; + if (from->si_code < 0) + return __copy_to_user(to, from, sizeof(siginfo_t)); + else { + int err; + + /* If you change siginfo_t structure, please be sure + this code is fixed accordingly. + It should never copy any pad contained in the structure + to avoid security leaks, but must copy the generic + 3 ints plus the relevant union member. */ + err = __put_user(from->si_signo, &to->si_signo); + err |= __put_user(from->si_errno, &to->si_errno); + err |= __put_user((short)from->si_code, &to->si_code); + /* First 32bits of unions are always present. */ + err |= __put_user(from->si_pid, &to->si_pid); + switch (from->si_code >> 16) { + case __SI_FAULT >> 16: + break; + case __SI_CHLD >> 16: + err |= __put_user(from->si_utime, &to->si_utime); + err |= __put_user(from->si_stime, &to->si_stime); + err |= __put_user(from->si_status, &to->si_status); + default: + err |= __put_user(from->si_uid, &to->si_uid); + break; + /* case __SI_RT: This is not generated by the kernel as of now. */ + } + return err; + } +} + /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -73,7 +110,7 @@ regs->gprs[2] = -EINTR; while (1) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule(); if (do_signal(regs, &saveset)) return -EINTR; @@ -101,7 +138,7 @@ regs->gprs[2] = -EINTR; while (1) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule(); if (do_signal(regs, &saveset)) return -EINTR; @@ -141,16 +178,15 @@ } asmlinkage int -sys_sigaltstack(const stack_t *uss, stack_t *uoss) +sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs) { - struct pt_regs *regs = (struct pt_regs *) &uss; return do_sigaltstack(uss, uoss, regs->gprs[15]); } -static int save_sigregs(struct pt_regs *regs,sigregs *sregs) +static int save_sigregs(struct pt_regs *regs,_sigregs *sregs) { int err; s390_fp_regs fpregs; @@ -165,7 +201,7 @@ } -static int restore_sigregs(struct pt_regs *regs,sigregs *sregs) +static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs) { int err; s390_fp_regs fpregs; @@ -187,13 +223,13 @@ static int restore_sigcontext(struct sigcontext *sc, pt_regs *regs, - sigregs *sregs,sigset_t *set) + _sigregs *sregs,sigset_t *set) { unsigned int err; err=restore_sigregs(regs,sregs); if(!err) - err=__copy_from_user(&set->sig,&sc->oldmask,SIGMASK_COPY_SIZE); + err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE); return(err); } @@ -229,15 +265,12 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) { rt_sigframe *frame = (rt_sigframe *)regs->gprs[15]; - stack_t st; if (sigreturn_common(regs,sizeof(rt_sigframe))) goto badframe; - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) - goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs->gprs[15]); + do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]); return regs->gprs[2]; badframe: @@ -292,7 +325,7 @@ err=__put_user(&frame->sregs,&frame->sc.sregs); if(!err) - err=__copy_to_user(&frame->sc.oldmask,&set->sig,SIGMASK_COPY_SIZE); + err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE); if(!err) { regs->gprs[2]=(current->exec_domain @@ -318,14 +351,17 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { + sigframe *frame; - if(!setup_frame_common(sig,ka,set,regs,sizeof(sigframe), - (S390_SYSCALL_OPCODE|__NR_sigreturn))) + if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe), + (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0) goto give_sigsegv; #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->eip, frame->pretcode); #endif + /* Martin wants this for pthreads */ + regs->gprs[3] = (addr_t)&frame->sc; return; give_sigsegv: @@ -345,7 +381,7 @@ (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0) goto give_sigsegv; - err = __copy_to_user(&frame->info, info, sizeof(*info)); + err = copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); @@ -354,8 +390,9 @@ err |= __put_user(sas_ss_flags(orig_sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - regs->gprs[3] = (u32)&frame->info; - regs->gprs[4] = (u32)&frame->uc; + err |= __put_user(&frame->sc,&frame->uc.sc); + regs->gprs[3] = (addr_t)&frame->info; + regs->gprs[4] = (addr_t)&frame->uc; if (err) goto give_sigsegv; @@ -454,10 +491,10 @@ if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; - current->state = TASK_STOPPED; + set_current_state(TASK_STOPPED); notify_parent(current, SIGCHLD); schedule(); @@ -513,7 +550,7 @@ /* FALLTHRU */ case SIGSTOP: - current->state = TASK_STOPPED; + set_current_state(TASK_STOPPED); current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); @@ -542,7 +579,7 @@ } /* Did we come from a system call? */ - if ( regs->trap == 0x20 /* System Call! */ ) { + if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) { /* Restart the system call - no handlers present */ if (regs->gprs[2] == -ERESTARTNOHAND || regs->gprs[2] == -ERESTARTSYS || diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/smp.c linux.ac/arch/s390/kernel/smp.c --- linux-2.4.0/arch/s390/kernel/smp.c Tue Sep 5 21:50:01 2000 +++ linux.ac/arch/s390/kernel/smp.c Fri Jan 5 00:00:32 2001 @@ -32,16 +32,15 @@ #include #include #include +#include #include "cpcmd.h" /* prototypes */ -extern void update_one_process( struct task_struct *p, - unsigned long ticks, unsigned long user, - unsigned long system, int cpu); extern int cpu_idle(void * unused); extern __u16 boot_cpu_addr; +extern volatile int __cpu_logical_map[]; /* * An array with a pointer the lowcore of every CPU. @@ -52,10 +51,8 @@ unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_old_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; -volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ cycles_t cacheflush_time=0; int smp_threads_ready=0; /* Set when the idlers are all forked. */ -unsigned long ipi_count=0; /* Number of IPIs delivered. */ static atomic_t smp_commenced = ATOMIC_INIT(0); spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; @@ -104,7 +101,7 @@ void machine_restart(char * __unused) { if (smp_processor_id() != 0) { - smp_ext_call_async(0, ec_restart); + smp_ext_bitcall(0, ec_restart); for (;;); } else do_machine_restart(); @@ -115,13 +112,13 @@ smp_send_stop(); if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) cpcmd(vmhalt_cmd, NULL, 0); - disabled_wait(0); + signal_processor(smp_processor_id(), sigp_stop_and_store_status); } void machine_halt(void) { if (smp_processor_id() != 0) { - smp_ext_call_async(0, ec_halt); + smp_ext_bitcall(0, ec_halt); for (;;); } else do_machine_halt(); @@ -132,13 +129,13 @@ smp_send_stop(); if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) cpcmd(vmpoff_cmd, NULL, 0); - disabled_wait(0); + signal_processor(smp_processor_id(), sigp_stop_and_store_status); } void machine_power_off(void) { if (smp_processor_id() != 0) { - smp_ext_call_async(0, ec_power_off); + smp_ext_bitcall(0, ec_power_off); for (;;); } else do_machine_power_off(); @@ -149,7 +146,7 @@ * cpus are handled. */ -void do_ext_call_interrupt(__u16 source_cpu_addr) +void do_ext_call_interrupt(struct pt_regs *regs, __u16 code) { ec_ext_call *ec, *next; int bits; @@ -172,6 +169,8 @@ do_machine_halt(); if (test_bit(ec_power_off, &bits)) do_machine_power_off(); + if (test_bit(ec_ptlb, &bits)) + local_flush_tlb(); /* * Handle external call commands with a parameter area @@ -184,7 +183,7 @@ return; /* no command signals */ /* Make a fifo out of the lifo */ - next = ec; + next = ec->next; ec->next = NULL; while (next != NULL) { ec_ext_call *tmp = next->next; @@ -196,61 +195,21 @@ /* Execute every sigp command on the queue */ while (ec != NULL) { switch (ec->cmd) { - case ec_get_ctl: { - ec_creg_parms *pp; - pp = (ec_creg_parms *) ec->parms; - atomic_set(&ec->status,ec_executing); - asm volatile ( - " bras 1,0f\n" - " stctl 0,0,0(%0)\n" - "0: ex %1,0(1)\n" - : : "a" (pp->cregs+pp->start_ctl), - "a" ((pp->start_ctl<<4) + pp->end_ctl) - : "memory", "1" ); - atomic_set(&ec->status,ec_done); - return; - } - case ec_set_ctl: { - ec_creg_parms *pp; - pp = (ec_creg_parms *) ec->parms; + case ec_callback_async: { + void (*func)(void *info); + void *info; + + func = ec->func; + info = ec->info; atomic_set(&ec->status,ec_executing); - asm volatile ( - " bras 1,0f\n" - " lctl 0,0,0(%0)\n" - "0: ex %1,0(1)\n" - : : "a" (pp->cregs+pp->start_ctl), - "a" ((pp->start_ctl<<4) + pp->end_ctl) - : "memory", "1" ); - atomic_set(&ec->status,ec_done); + (func)(info); return; } - case ec_set_ctl_masked: { - ec_creg_mask_parms *pp; - u32 cregs[16]; - int i; - - pp = (ec_creg_mask_parms *) ec->parms; + case ec_callback_sync: atomic_set(&ec->status,ec_executing); - asm volatile ( - " bras 1,0f\n" - " stctl 0,0,0(%0)\n" - "0: ex %1,0(1)\n" - : : "a" (cregs+pp->start_ctl), - "a" ((pp->start_ctl<<4) + pp->end_ctl) - : "memory", "1" ); - for (i = pp->start_ctl; i <= pp->end_ctl; i++) - cregs[i] = (cregs[i] & pp->andvals[i]) - | pp->orvals[i]; - asm volatile ( - " bras 1,0f\n" - " lctl 0,0,0(%0)\n" - "0: ex %1,0(1)\n" - : : "a" (cregs+pp->start_ctl), - "a" ((pp->start_ctl<<4) + pp->end_ctl) - : "memory", "1" ); + (ec->func)(ec->info); atomic_set(&ec->status,ec_done); return; - } default: } ec = ec->next; @@ -258,17 +217,19 @@ } /* - * Send an external call sigp to another cpu and wait for its completion. + * Send a callback sigp to another cpu. */ -sigp_ccode smp_ext_call_sync(int cpu, ec_cmd_sig cmd, void *parms) +sigp_ccode +smp_ext_call(int cpu, void (*func)(void *info), void *info, int wait) { struct _lowcore *lowcore = &get_cpu_lowcore(cpu); sigp_ccode ccode; ec_ext_call ec; - ec.cmd = cmd; + ec.cmd = wait ? ec_callback_sync : ec_callback_async; atomic_set(&ec.status, ec_pending); - ec.parms = parms; + ec.func = func; + ec.info = info; do { ec.next = (ec_ext_call*) atomic_read(&lowcore->ext_call_queue); } while (atomic_compare_and_swap((int) ec.next, (int)(&ec), @@ -288,34 +249,15 @@ if (ccode != sigp_not_operational) /* wait for completion, FIXME: possible seed of a deadlock */ - while (atomic_read(&ec.status) != ec_done); - - return ccode; -} - -/* - * Send an external call sigp to another cpu and return without waiting - * for its completion. Currently we do not support parameters with - * asynchronous sigps. - */ -sigp_ccode smp_ext_call_async(int cpu, ec_bit_sig sig) -{ - struct _lowcore *lowcore = &get_cpu_lowcore(cpu); - sigp_ccode ccode; + while (atomic_read(&ec.status) != (wait?ec_done:ec_executing)); - /* - * Set signaling bit in lowcore of target cpu and kick it - */ - atomic_set_mask(1<ext_call_fast); - ccode = signal_processor(cpu, sigp_external_call); return ccode; } /* - * Send an external call sigp to every other cpu in the system and - * wait for the completion of the sigps. + * Send a callback sigp to every other cpu in the system. */ -void smp_ext_call_sync_others(ec_cmd_sig cmd, void *parms) +void smp_ext_call_others(void (*func)(void *info), void *info, int wait) { struct _lowcore *lowcore; ec_ext_call ec[NR_CPUS]; @@ -326,9 +268,10 @@ if (smp_processor_id() == i) continue; lowcore = &get_cpu_lowcore(i); - ec[i].cmd = cmd; - atomic_set(&ec[i].status, ec_pending); - ec[i].parms = parms; + ec[i].cmd = wait ? ec_callback_sync : ec_callback_async; + atomic_set(&ec[i].status, ec_pending); + ec[i].func = func; + ec[i].info = info; do { ec[i].next = (ec_ext_call *) atomic_read(&lowcore->ext_call_queue); @@ -341,16 +284,33 @@ for (i = 0; i < smp_num_cpus; i++) { if (smp_processor_id() == i) continue; - while (atomic_read(&ec[i].status) != ec_done); + while (atomic_read(&ec[i].status) != + (wait ? ec_done:ec_executing)); } } /* + * Send an external call sigp to another cpu and return without waiting + * for its completion. + */ +sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig) +{ + struct _lowcore *lowcore = &get_cpu_lowcore(cpu); + sigp_ccode ccode; + + /* + * Set signaling bit in lowcore of target cpu and kick it + */ + atomic_set_mask(1<ext_call_fast); + ccode = signal_processor(cpu, sigp_external_call); + return ccode; +} + +/* * Send an external call sigp to every other cpu in the system and - * return without waiting for the completion of the sigps. Currently - * we do not support parameters with asynchronous sigps. + * return without waiting for its completion. */ -void smp_ext_call_async_others(ec_bit_sig sig) +void smp_ext_bitcall_others(ec_bit_sig sig) { struct _lowcore *lowcore; sigp_ccode ccode; @@ -420,7 +380,46 @@ void smp_send_stop(void) { - smp_signal_others(sigp_stop, 0, 1, NULL); + int i; + u32 dummy; + unsigned long low_core_addr; + + /* write magic number to zero page (absolute 0) */ + + get_cpu_lowcore(smp_processor_id()).panic_magic = __PANIC_MAGIC; + + /* stop all processors */ + + smp_signal_others(sigp_stop, 0, TRUE, NULL); + + /* store status of all processors in their lowcores (real 0) */ + + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() != i) { + int ccode; + low_core_addr = (unsigned long)&get_cpu_lowcore(i); + do { + ccode = signal_processor_ps( + &dummy, + low_core_addr, + i, + sigp_store_status_at_address); + } while(ccode == sigp_busy); + } + } +} + +/* + * this function sends a 'purge tlb' signal to another CPU. + */ +void smp_ptlb_callback(void *info) +{ + local_flush_tlb(); +} + +void smp_ptlb_all(void) +{ + smp_ext_call_others(smp_ptlb_callback, NULL, 1); } /* @@ -431,7 +430,44 @@ void smp_send_reschedule(int cpu) { - smp_ext_call_async(cpu, ec_schedule); + smp_ext_bitcall(cpu, ec_schedule); +} + +/* + * parameter area for the set/clear control bit callbacks + */ +typedef struct +{ + __u16 start_ctl; + __u16 end_ctl; + __u32 orvals[16]; + __u32 andvals[16]; +} ec_creg_mask_parms; + +/* + * callback for setting/clearing control bits + */ +void smp_ctl_bit_callback(void *info) { + ec_creg_mask_parms *pp; + u32 cregs[16]; + int i; + + pp = (ec_creg_mask_parms *) info; + asm volatile (" bras 1,0f\n" + " stctl 0,0,0(%0)\n" + "0: ex %1,0(1)\n" + : : "a" (cregs+pp->start_ctl), + "a" ((pp->start_ctl<<4) + pp->end_ctl) + : "memory", "1" ); + for (i = pp->start_ctl; i <= pp->end_ctl; i++) + cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i]; + asm volatile (" bras 1,0f\n" + " lctl 0,0,0(%0)\n" + "0: ex %1,0(1)\n" + : : "a" (cregs+pp->start_ctl), + "a" ((pp->start_ctl<<4) + pp->end_ctl) + : "memory", "1" ); + return; } /* @@ -445,7 +481,7 @@ parms.end_ctl = cr; parms.orvals[cr] = 1 << bit; parms.andvals[cr] = 0xFFFFFFFF; - smp_ext_call_sync_others(ec_set_ctl_masked,&parms); + smp_ext_call_others(smp_ctl_bit_callback, &parms, 1); } __ctl_set_bit(cr, bit); } @@ -461,11 +497,35 @@ parms.end_ctl = cr; parms.orvals[cr] = 0x00000000; parms.andvals[cr] = ~(1 << bit); - smp_ext_call_sync_others(ec_set_ctl_masked,&parms); + smp_ext_call_others(smp_ctl_bit_callback, &parms, 1); } __ctl_clear_bit(cr, bit); } +/* + * Call a function on all other processors + */ + +int +smp_call_function(void (*func)(void *info), void *info, int retry, int wait) +/* + * [SUMMARY] Run a function on all other CPUs. + * The function to run. This must be fast and non-blocking. + * An arbitrary pointer to pass to the function. + * currently unused. + * If true, wait (atomically) until function has completed on other CPUs. + * [RETURNS] 0 on success, else a negative status code. Does not return until + * remote CPUs are nearly ready to execute <> or are or have executed. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler, you may call it from a bottom half handler. + */ +{ + if (atomic_read(&smp_commenced) != 0) + smp_ext_call_others(func, info, 1); + (func)(info); + return 0; +} /* * Lets check how many CPUs we have. @@ -475,7 +535,6 @@ { int curr_cpu; - __cpu_logical_map[0] = boot_cpu_addr; current->processor = 0; smp_num_cpus = 1; for (curr_cpu = 0; @@ -527,7 +586,7 @@ struct pt_regs regs; /* don't care about the psw and regs settings since we'll never reschedule the forked task. */ - memset(®s,sizeof(pt_regs),0); + memset(®s,0,sizeof(pt_regs)); return do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); } @@ -594,7 +653,10 @@ struct _lowcore *curr_lowcore; sigp_ccode ccode; int i; - + + /* request the 0x1202 external interrupt */ + if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0) + panic("Couldn't request external interrupt 0x1202"); smp_count_cpus(); memset(lowcore_ptr,0,sizeof(lowcore_ptr)); @@ -705,24 +767,7 @@ */ irq_enter(cpu, 0); - update_one_process(p, 1, user, system, cpu); - if (p->pid) { - p->counter -= 1; - if (p->counter <= 0) { - p->counter = 0; - p->need_resched = 1; - } - if (p->nice > 0) { - kstat.cpu_nice += user; - kstat.per_cpu_nice[cpu] += user; - } else { - kstat.cpu_user += user; - kstat.per_cpu_user[cpu] += user; - } - kstat.cpu_system += system; - kstat.per_cpu_system[cpu] += system; - - } + update_process_times(user); irq_exit(cpu, 0); } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/sys_s390.c linux.ac/arch/s390/kernel/sys_s390.c --- linux-2.4.0/arch/s390/kernel/sys_s390.c Wed Jul 5 19:31:01 2000 +++ linux.ac/arch/s390/kernel/sys_s390.c Fri Jan 5 00:00:32 2001 @@ -71,18 +71,10 @@ return error; } -/* FIXME: 6 parameters is one too much ... */ -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - /* * Perform the select(nd, in, out, ex, tv) and mmap() system - * calls. Linux/i386 didn't use to be able to handle more than - * 4 system call parameters, so these system calls used a memory + * calls. Linux for S/390 isn't able to handle more than 5 + * system call parameters, so these system calls used a memory * block for parameter passing.. */ @@ -95,6 +87,18 @@ unsigned long offset; }; +asmlinkage long sys_mmap2(struct mmap_arg_struct *arg) +{ + struct mmap_arg_struct a; + int error = -EFAULT; + + if (copy_from_user(&a, arg, sizeof(a))) + goto out; + error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); +out: + return error; +} + asmlinkage int old_mmap(struct mmap_arg_struct *arg) { struct mmap_arg_struct a; @@ -239,7 +243,7 @@ asmlinkage int sys_pause(void) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule(); return -ERESTARTNOHAND; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/time.c linux.ac/arch/s390/kernel/time.c --- linux-2.4.0/arch/s390/kernel/time.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/kernel/time.c Fri Jan 5 00:00:32 2001 @@ -11,7 +11,6 @@ * Copyright (C) 1991, 1992, 1995 Linus Torvalds */ -#include #include #include #include @@ -27,15 +26,14 @@ #include #include +#include -#include #include +#include #include -extern volatile unsigned long lost_ticks; - /* change this if you have some constant time drift */ #define USECS_PER_JIFFY ((signed long)1000000/HZ) #define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12) @@ -45,6 +43,7 @@ static uint64_t init_timer_cc, last_timer_cc; extern rwlock_t xtime_lock; +extern unsigned long wall_jiffies; void tod_to_timeval(uint64_t todval, struct timeval *xtime) { @@ -94,9 +93,9 @@ */ void do_gettimeofday(struct timeval *tv) { - extern volatile unsigned long lost_ticks; unsigned long flags; unsigned long usec, sec; + unsigned long lost_ticks = jiffies - wall_jiffies; read_lock_irqsave(&xtime_lock, flags); usec = do_gettimeoffset(); @@ -149,7 +148,7 @@ extern __u16 boot_cpu_addr; #endif -void do_timer_interrupt(struct pt_regs *regs,int error_code) +void do_timer_interrupt(struct pt_regs *regs, __u16 error_code) { unsigned long flags; @@ -242,6 +241,9 @@ printk("time_init: TOD clock stopped/non-operational\n"); break; } + /* request the 0x1004 external interrupt */ + if (register_external_interrupt(0x1004, do_timer_interrupt) != 0) + panic("Couldn't request external interrupts 0x1004"); init_100hz_timer(); init_timer_cc = S390_lowcore.jiffy_timer_cc; init_timer_cc -= 0x8126d60e46000000LL - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/kernel/traps.c linux.ac/arch/s390/kernel/traps.c --- linux-2.4.0/arch/s390/kernel/traps.c Mon Dec 4 01:48:19 2000 +++ linux.ac/arch/s390/kernel/traps.c Fri Jan 5 00:00:32 2001 @@ -42,122 +42,15 @@ typedef void pgm_check_handler_t(struct pt_regs *, long); pgm_check_handler_t *pgm_check_table[128]; -extern pgm_check_handler_t default_trap_handler; -extern pgm_check_handler_t do_page_fault; - -asmlinkage int system_call(void); - -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void name(struct pt_regs * regs, long error_code) \ -{ \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - die_if_no_fixup(str,regs,error_code); \ - force_sig(signr, tsk); \ -} - -/* TODO: define these as 'pgm_check_handler_t xxx;' -asmlinkage void divide_error(void); -asmlinkage void debug(void); -asmlinkage void nmi(void); -asmlinkage void int3(void); -asmlinkage void overflow(void); -asmlinkage void bounds(void); -asmlinkage void invalid_op(void); -asmlinkage void device_not_available(void); -asmlinkage void double_fault(void); -asmlinkage void coprocessor_segment_overrun(void); -asmlinkage void invalid_TSS(void); -asmlinkage void segment_not_present(void); -asmlinkage void stack_segment(void); -asmlinkage void general_protection(void); -asmlinkage void coprocessor_error(void); -asmlinkage void reserved(void); -asmlinkage void alignment_check(void); -asmlinkage void spurious_interrupt_bug(void); -*/ - -int kstack_depth_to_print = 24; - -/* - * These constants are for searching for possible module text - * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is - * a guess of how much space is likely to be vmalloced. - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define MODULE_RANGE (8*1024*1024) - -void show_crashed_task_info(void) -{ - printk("CPU: %d\n",smp_processor_id()); - printk("Process %s (pid: %d, stackpage=%08X)\n", - current->comm, current->pid, 4096+(addr_t)current); - show_regs(current,NULL,NULL); -} -#if 0 -static void show_registers(struct pt_regs *regs) -{ - printk("CPU: %d\nPSW: %08lx %08lx\n", - smp_processor_id(), (unsigned long) regs->psw.mask, - (unsigned long) regs->psw.addr); - printk("GPRS:\n"); - - printk("%08lx %08lx %08lx %08lx\n", - regs->gprs[0], regs->gprs[1], - regs->gprs[2], regs->gprs[3]); - printk("%08lx %08lx %08lx %08lx\n", - regs->gprs[4], regs->gprs[5], - regs->gprs[6], regs->gprs[7]); - printk("%08lx %08lx %08lx %08lx\n", - regs->gprs[8], regs->gprs[9], - regs->gprs[10], regs->gprs[11]); - printk("%08lx %08lx %08lx %08lx\n", - regs->gprs[12], regs->gprs[13], - regs->gprs[14], regs->gprs[15]); - printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ", - current->comm, current->pid, 4096+(unsigned long)current); -/* - stack = (unsigned long *) esp; - for(i=0; i < kstack_depth_to_print; i++) { - if (((long) stack & 4095) == 0) - break; - if (i && ((i % 8) == 0)) - printk("\n "); - printk("%08lx ", get_seg_long(ss,stack++)); - } - printk("\nCall Trace: "); - stack = (unsigned long *) esp; - i = 1; - module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT); - module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)); - module_end = module_start + MODULE_RANGE; - while (((long) stack & 4095) != 0) { - addr = get_seg_long(ss, stack++); */ - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ -/* if (((addr >= (unsigned long) &_stext) && - (addr <= (unsigned long) &_etext)) || - ((addr >= module_start) && (addr <= module_end))) { - if (i && ((i % 8) == 0)) - printk("\n "); - printk("[<%08lx>] ", addr); - i++; - } - } - printk("\nCode: "); - for(i=0;i<20;i++) - printk("%02x ",0xff & get_seg_byte(regs->xcs & 0xffff,(i+(char *)regs->eip))); - printk("\n"); -*/ -} +#ifdef CONFIG_SYSCTL +#ifdef CONFIG_PROCESS_DEBUG +int sysctl_userprocess_debug = 1; +#else +int sysctl_userprocess_debug = 0; +#endif #endif +extern pgm_check_handler_t do_page_fault; spinlock_t die_lock; @@ -166,29 +59,65 @@ console_verbose(); spin_lock_irq(&die_lock); printk("%s: %04lx\n", str, err & 0xffff); - show_crashed_task_info(); + show_regs(regs); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } -int check_for_fixup(struct pt_regs * regs) -{ - if (!(regs->psw.mask & PSW_PROBLEM_STATE)) { - unsigned long fixup; - fixup = search_exception_table(regs->psw.addr); - if (fixup) { - regs->psw.addr = fixup; - return 1; +#define DO_ERROR(signr, str, name) \ +asmlinkage void name(struct pt_regs * regs, long interruption_code) \ +{ \ + do_trap(interruption_code, signr, str, regs, NULL); \ +} + +#define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \ +asmlinkage void name(struct pt_regs * regs, long interruption_code) \ +{ \ + siginfo_t info; \ + info.si_signo = signr; \ + info.si_errno = 0; \ + info.si_code = sicode; \ + info.si_addr = (void *)siaddr; \ + do_trap(interruption_code, signr, str, regs, &info); \ +} + +static void inline do_trap(long interruption_code, int signr, char *str, + struct pt_regs *regs, siginfo_t *info) +{ + if (regs->psw.mask & PSW_PROBLEM_STATE) { + struct task_struct *tsk = current; + tsk->thread.trap_no = interruption_code; + if (info) + force_sig_info(signr, info, tsk); + else + force_sig(signr, tsk); +#ifndef CONFIG_SYSCTL +#ifdef CONFIG_PROCESS_DEBUG + printk("User process fault: interruption code 0x%lX\n", + interruption_code); + show_regs(regs); +#endif +#else + if (sysctl_userprocess_debug) { + printk("User process fault: interruption code 0x%lX\n", + interruption_code); + show_regs(regs); } - } - return 0; +#endif + } else { + unsigned long fixup = search_exception_table(regs->psw.addr); + if (fixup) + regs->psw.addr = fixup; + else + die(str, regs, interruption_code); + } } int do_debugger_trap(struct pt_regs *regs,int signal) { if(regs->psw.mask&PSW_PROBLEM_STATE) { - if(current->flags & PF_PTRACED) + if(current->ptrace & PT_PTRACED) force_sig(signal,current); else return 1; @@ -207,50 +136,16 @@ return 0; } -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!(regs->psw.mask & PSW_PROBLEM_STATE)) { - unsigned long fixup; - fixup = search_exception_table(regs->psw.addr); - if (fixup) { - regs->psw.addr = fixup; - return; - } - die(str, regs, err); - } -} - -asmlinkage void default_trap_handler(struct pt_regs * regs, long error_code) -{ - current->thread.error_code = error_code; - current->thread.trap_no = error_code; - die_if_no_fixup("Unknown program exception",regs,error_code); - force_sig(SIGSEGV, current); -} - -DO_ERROR(2, SIGILL, "privileged operation", privileged_op, current) -DO_ERROR(3, SIGILL, "execute exception", execute_exception, current) -DO_ERROR(5, SIGSEGV, "addressing exception", addressing_exception, current) -DO_ERROR(9, SIGFPE, "fixpoint divide exception", divide_exception, current) -DO_ERROR(0x12, SIGILL, "translation exception", translation_exception, current) -DO_ERROR(0x13, SIGILL, "special operand exception", special_op_exception, current) -DO_ERROR(0x15, SIGILL, "operand exception", operand_exception, current) - -/* need to define -DO_ERROR( 6, SIGILL, "invalid operand", invalid_op, current) -DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current) -DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math) -DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current) -DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) -DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) -DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) -DO_ERROR(18, SIGSEGV, "reserved", reserved, current) -DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current) -*/ - -#ifdef CONFIG_IEEEFPU_EMULATION +DO_ERROR(SIGSEGV, "Unknown program exception", default_trap_handler) +DO_ERROR(SIGILL, "privileged operation", privileged_op) +DO_ERROR(SIGILL, "execute exception", execute_exception) +DO_ERROR(SIGSEGV, "addressing exception", addressing_exception) +DO_ERROR(SIGFPE, "fixpoint divide exception", divide_exception) +DO_ERROR(SIGILL, "translation exception", translation_exception) +DO_ERROR(SIGILL, "special operand exception", special_op_exception) +DO_ERROR(SIGILL, "operand exception", operand_exception) -asmlinkage void illegal_op(struct pt_regs * regs, long error_code) +asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) { __u8 opcode[6]; __u16 *location; @@ -268,6 +163,7 @@ if(do_debugger_trap(regs,SIGTRAP)) do_sig=1; } +#ifdef CONFIG_IEEEFPU_EMULATION else if (problem_state ) { if (opcode[0] == 0xb3) { @@ -288,18 +184,19 @@ do_sig = math_emu_lfpc(opcode, regs); } else do_sig = 1; - } else - do_sig = 1; - if (do_sig) { - current->thread.error_code = error_code; - current->thread.trap_no = 1; - force_sig(SIGILL, current); - die_if_no_fixup("illegal operation", regs, error_code); } +#endif + else + do_sig = 1; + if (do_sig) + do_trap(interruption_code, SIGILL, "illegal operation", regs, NULL); unlock_kernel(); } -asmlinkage void specification_exception(struct pt_regs * regs, long error_code) + + +#ifdef CONFIG_IEEEFPU_EMULATION +asmlinkage void specification_exception(struct pt_regs * regs, long interruption_code) { __u8 opcode[6]; __u16 *location; @@ -311,26 +208,26 @@ get_user(*((__u16 *) opcode), location); switch (opcode[0]) { case 0x28: /* LDR Rx,Ry */ - math_emu_ldr(opcode); + do_sig=math_emu_ldr(opcode); break; case 0x38: /* LER Rx,Ry */ - math_emu_ler(opcode); + do_sig=math_emu_ler(opcode); break; case 0x60: /* STD R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_std(opcode, regs); + do_sig=math_emu_std(opcode, regs); break; case 0x68: /* LD R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_ld(opcode, regs); + do_sig=math_emu_ld(opcode, regs); break; case 0x70: /* STE R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_ste(opcode, regs); + do_sig=math_emu_ste(opcode, regs); break; case 0x78: /* LE R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_le(opcode, regs); + do_sig=math_emu_le(opcode, regs); break; default: do_sig = 1; @@ -338,47 +235,59 @@ } } else do_sig = 1; - if (do_sig) { - current->thread.error_code = error_code; - current->thread.trap_no = 1; - force_sig(SIGILL, current); - die_if_no_fixup("illegal operation", regs, error_code); - } + if (do_sig) + do_trap(interruption_code, SIGILL, "specification exception", regs, NULL); unlock_kernel(); } +#else +DO_ERROR(SIGILL, "specification exception", specification_exception) +#endif -asmlinkage void data_exception(struct pt_regs * regs, long error_code) +asmlinkage void data_exception(struct pt_regs * regs, long interruption_code) { __u8 opcode[6]; __u16 *location; int do_sig = 0; lock_kernel(); - if (regs->psw.mask & 0x00010000L) { - location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); + location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); + if(MACHINE_HAS_IEEE) + { + __asm__ volatile ("stfpc %0\n\t" + : "=m" (current->thread.fp_regs.fpc)); + } + /* Same code should work when we implement fpu emulation */ + /* provided we call data exception from the fpu emulator */ + if(current->thread.fp_regs.fpc&FPC_DXC_MASK) + { + current->thread.ieee_instruction_pointer=(addr_t)location; + force_sig(SIGFPE, current); + } +#ifdef CONFIG_IEEEFPU_EMULATION + else if (regs->psw.mask & 0x00010000L) { get_user(*((__u16 *) opcode), location); switch (opcode[0]) { case 0x28: /* LDR Rx,Ry */ - math_emu_ldr(opcode); + do_sig=math_emu_ldr(opcode); break; case 0x38: /* LER Rx,Ry */ - math_emu_ler(opcode); + do_sig=math_emu_ler(opcode); break; case 0x60: /* STD R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_std(opcode, regs); + do_sig=math_emu_std(opcode, regs); break; case 0x68: /* LD R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_ld(opcode, regs); + do_sig=math_emu_ld(opcode, regs); break; case 0x70: /* STE R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_ste(opcode, regs); + do_sig=math_emu_ste(opcode, regs); break; case 0x78: /* LE R,D(X,B) */ get_user(*((__u16 *) (opcode+2)), location+1); - math_emu_le(opcode, regs); + do_sig=math_emu_le(opcode, regs); break; case 0xb3: get_user(*((__u16 *) (opcode+2)), location+1); @@ -406,22 +315,15 @@ do_sig = 1; break; } - } else - do_sig = 1; - if (do_sig) { - current->thread.error_code = error_code; - current->thread.trap_no = 1; - force_sig(SIGILL, current); - die_if_no_fixup("illegal operation", regs, error_code); } +#endif + else + do_sig = 1; + if (do_sig) + do_trap(interruption_code, SIGILL, "data exception", regs, NULL); unlock_kernel(); } -#else -DO_ERROR(1, SIGILL, "illegal operation", illegal_op, current) -DO_ERROR(6, SIGILL, "specification exception", specification_exception, current) -DO_ERROR(7, SIGILL, "data exception", data_exception, current) -#endif /* CONFIG_IEEEFPU_EMULATION */ /* init is done in lowcore.S and head.S */ @@ -463,7 +365,7 @@ /* I've seen this possibly a task structure being reused ? */ printk("Spurious per exception detected\n"); printk("switching off per tracing for this task.\n"); - show_crashed_task_info(); + show_regs(regs); /* Hopefully switching off per tracing will help us survive */ regs->psw.mask &= ~PSW_PER_MASK; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/lib/Makefile linux.ac/arch/s390/lib/Makefile --- linux-2.4.0/arch/s390/lib/Makefile Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/lib/Makefile Fri Jan 5 00:00:32 2001 @@ -2,11 +2,17 @@ # Makefile for s390-specific library files.. # +ifdef SMP .S.o: - $(CC) $(AFLAGS) -traditional -c $< -o $*.o + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o +else +.S.o: + $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o +endif L_TARGET = lib.a -L_OBJS = checksum.o delay.o memset.o strcmp.o strncpy.o + +obj-y = checksum.o delay.o memset.o strcmp.o strncpy.o uaccess.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/lib/delay.c linux.ac/arch/s390/lib/delay.c --- linux-2.4.0/arch/s390/lib/delay.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/lib/delay.c Fri Jan 5 00:00:32 2001 @@ -11,35 +11,39 @@ * Copyright (C) 1997 Martin Mares */ -#include #include #include -#ifdef CONFIG_SMP +#ifdef __SMP__ #include #endif void __delay(unsigned long loops) { - __asm__ __volatile__( - "0: ahi %0,-1\n" - " jnm 0b" - : /* no outputs */ : "r" (loops) ); + /* + * To end the bloody studid and useless discussion about the + * BogoMips number I took the liberty to define the __delay + * function in a way that that resulting BogoMips number will + * yield the megahertz number of the cpu. The important function + * is udelay and that is done using the tod clock. -- martin. + */ + __asm__ __volatile__( + "0: brct %0,0b" + : /* no outputs */ : "r" (loops/2) ); } -inline void __const_udelay(unsigned long xloops) +/* + * Waits for 'usecs' microseconds using the tod clock + */ +void __udelay(unsigned long usecs) { + uint64_t start_cc, end_cc; - __asm__("LR 3,%1\n\t" - "MR 2,%2\n\t" - "LR %0,2\n\t" - : "=r" (xloops) - : "r" (xloops) , "r" (loops_per_sec) - : "2" , "3"); - __delay(xloops); + if (usecs == 0) + return; + asm volatile ("STCK %0" : "=m" (start_cc)); + do { + asm volatile ("STCK %0" : "=m" (end_cc)); + } while (((end_cc - start_cc)/4096) < usecs); } -void __udelay(unsigned long usecs) -{ - __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ -} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/lib/strcmp.S linux.ac/arch/s390/lib/strcmp.S --- linux-2.4.0/arch/s390/lib/strcmp.S Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/lib/strcmp.S Fri Jan 5 00:00:32 2001 @@ -18,8 +18,8 @@ CLST 2,3 JO .-4 JE strcmp_equal - IC 0,0(0,3) - IC 1,0(0,2) + IC 0,0(3) + IC 1,0(2) SR 1,0 strcmp_equal: LR 2,1 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/lib/strncpy.S linux.ac/arch/s390/lib/strncpy.S --- linux-2.4.0/arch/s390/lib/strncpy.S Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/lib/strncpy.S Fri Jan 5 00:00:32 2001 @@ -20,9 +20,9 @@ SR 0,0 strncpy_loop: ICM 0,1,0(3) # ICM sets the cc, IC does not - LA 3,1(0,3) - STC 0,0(0,1) - LA 1,1(0,1) + LA 3,1(3) + STC 0,0(1) + LA 1,1(1) JZ strncpy_exit # ICM inserted a 0x00 BRCT 4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0 strncpy_exit: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/lib/uaccess.S linux.ac/arch/s390/lib/uaccess.S --- linux-2.4.0/arch/s390/lib/uaccess.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/s390/lib/uaccess.S Fri Jan 5 00:00:32 2001 @@ -0,0 +1,51 @@ +/* + * arch/s390/lib/uaccess.S + * fixup routines for copy_{from|to}_user functions. + * + * s390 + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * These functions have a non-standard call interface + */ + +#include + + .text + .align 4 + .globl __copy_from_user_fixup +__copy_from_user_fixup: + l 1,__LC_PGM_OLD_PSW+4 + sll 4,1 + srl 4,1 +0: lhi 3,-4096 + sll 3,1 + srl 3,1 + n 3,__LC_TRANS_EXC_ADDR + sr 3,4 + bm 4(1) +1: mvcle 2,4,0 + b 4(1) + .section __ex_table,"a" + .long 1b,0b + .previous + + .align 4 + .text + .globl __copy_to_user_fixup +__copy_to_user_fixup: + l 1,__LC_PGM_OLD_PSW+4 + sll 4,1 + srl 4,1 +0: lhi 5,-4096 + sll 5,1 + srl 5,1 + n 5,__LC_TRANS_EXC_ADDR + sr 5,4 + bm 4(1) +1: mvcle 4,2,0 + b 4(1) + .section __ex_table,"a" + .long 1b,0b + .previous + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/mm/Makefile linux.ac/arch/s390/mm/Makefile --- linux-2.4.0/arch/s390/mm/Makefile Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/mm/Makefile Fri Jan 5 00:00:32 2001 @@ -8,6 +8,7 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o fault.o ioremap.o extable.o + +obj-y := init.o fault.o ioremap.o extable.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/mm/fault.c linux.ac/arch/s390/mm/fault.c --- linux-2.4.0/arch/s390/mm/fault.c Sat Aug 5 00:15:37 2000 +++ linux.ac/arch/s390/mm/fault.c Fri Jan 5 00:00:32 2001 @@ -26,6 +26,10 @@ #include #include +#ifdef CONFIG_SYSCTL +extern int sysctl_userprocess_debug; +#endif + extern void die(const char *,struct pt_regs *,long); /* @@ -48,6 +52,8 @@ int write; unsigned long psw_mask; unsigned long psw_addr; + int si_code = SEGV_MAPERR; + int kernel_address = 0; /* * get psw mask of Program old psw to find out, @@ -65,58 +71,106 @@ address = S390_lowcore.trans_exc_code&0x7ffff000; - if (in_irq()) - die("page fault from irq handler",regs,error_code); - tsk = current; mm = tsk->mm; + if (in_interrupt() || !mm) + goto no_context; + + + /* + * Check which address space the address belongs to + */ + switch (S390_lowcore.trans_exc_code & 3) + { + case 0: /* Primary Segment Table Descriptor */ + kernel_address = 1; + goto no_context; + + case 1: /* STD determined via access register */ + if (S390_lowcore.exc_access_id == 0) + { + kernel_address = 1; + goto no_context; + } + if (regs && S390_lowcore.exc_access_id < NUM_ACRS) + { + if (regs->acrs[S390_lowcore.exc_access_id] == 0) + { + kernel_address = 1; + goto no_context; + } + if (regs->acrs[S390_lowcore.exc_access_id] == 1) + { + /* user space address */ + break; + } + } + die("page fault via unknown access register", regs, error_code); + break; + + case 2: /* Secondary Segment Table Descriptor */ + case 3: /* Home Segment Table Descriptor */ + /* user space address */ + break; + } + + + /* + * When we get here, the fault happened in the current + * task's user address space, so we search the VMAs + */ + down(&mm->mmap_sem); vma = find_vma(mm, address); - if (!vma) { - printk("no vma for address %lX\n",address); + if (!vma) goto bad_area; - } if (vma->vm_start <= address) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) { - printk("VM_GROWSDOWN not set, but address %lX \n",address); - printk("not in vma %p (start %lX end %lX)\n",vma, - vma->vm_start,vma->vm_end); + if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - } - if (expand_stack(vma, address)) { - printk("expand of vma failed address %lX\n",address); - printk("vma %p (start %lX end %lX)\n",vma, - vma->vm_start,vma->vm_end); + if (expand_stack(vma, address)) goto bad_area; - } /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: write = 0; + si_code = SEGV_ACCERR; + switch (error_code & 0xFF) { case 0x04: /* write, present*/ write = 1; break; case 0x10: /* not present*/ case 0x11: /* not present*/ - if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) { - printk("flags %X of vma for address %lX wrong \n", - vma->vm_flags,address); - printk("vma %p (start %lX end %lX)\n",vma, - vma->vm_start,vma->vm_end); + if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) goto bad_area; - } break; default: printk("code should be 4, 10 or 11 (%lX) \n",error_code&0xFF); goto bad_area; } - handle_mm_fault(tsk, vma, address, write); + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + switch (handle_mm_fault(mm, vma, address, write)) { + case 1: + tsk->min_flt++; + break; + case 2: + tsk->maj_flt++; + break; + case 0: + goto do_sigbus; + default: + goto out_of_memory; + } up(&mm->mmap_sem); return; @@ -130,19 +184,32 @@ /* User mode accesses just cause a SIGSEGV */ if (psw_mask & PSW_PROBLEM_STATE) { + struct siginfo si; tsk->thread.prot_addr = address; - tsk->thread.error_code = error_code; - tsk->thread.trap_no = 14; - + tsk->thread.trap_no = error_code; +#ifndef CONFIG_SYSCTL +#ifdef CONFIG_PROCESS_DEBUG printk("User process fault: interruption code 0x%lX\n",error_code); printk("failing address: %lX\n",address); - show_crashed_task_info(); - force_sig(SIGSEGV, tsk); + show_regs(regs); +#endif +#else + if (sysctl_userprocess_debug) { + printk("User process fault: interruption code 0x%lX\n", + error_code); + printk("failing address: %lX\n", address); + show_regs(regs); + } +#endif + si.si_signo = SIGSEGV; + si.si_code = si_code; + si.si_addr = (void*) address; + force_sig_info(SIGSEGV, &si, tsk); return; } +no_context: /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(regs->psw.addr)) != 0) { regs->psw.addr = fixup; return; @@ -151,53 +218,47 @@ /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. - * - * First we check if it was the bootup rw-test, though.. */ - if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + + if (kernel_address) + printk(KERN_ALERT "Unable to handle kernel pointer dereference" + " at virtual kernel address %08lx\n", address); else - printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n",address); + printk(KERN_ALERT "Unable to handle kernel paging request" + " at virtual user address %08lx\n", address); /* * need to define, which information is useful here */ - lock_kernel(); die("Oops", regs, error_code); do_exit(SIGKILL); - unlock_kernel(); -} -/* - { - char c; - int i,j; - char *addr; - addr = ((char*) psw_addr)-0x20; - for (i=0;i<16;i++) { - if (i == 2) - printk("\n"); - printk ("%08X: ",(unsigned long) addr); - for (j=0;j<4;j++) { - printk("%08X ",*(unsigned long*)addr); - addr += 4; - } - addr -=0x10; - printk(" | "); - for (j=0;j<16;j++) { - printk("%c",(c=*addr++) < 0x20 ? '.' : c ); - } - - printk("\n"); - } - printk("\n"); - } +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. */ - - - - +out_of_memory: + up(&mm->mmap_sem); + printk("VM: killing process %s\n", tsk->comm); + if (psw_mask & PSW_PROBLEM_STATE) + do_exit(SIGKILL); + goto no_context; + +do_sigbus: + up(&mm->mmap_sem); + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + tsk->thread.prot_addr = address; + tsk->thread.trap_no = error_code; + force_sig(SIGBUS, tsk); + + /* Kernel mode? Handle exceptions or die */ + if (!(psw_mask & PSW_PROBLEM_STATE)) + goto no_context; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/mm/init.c linux.ac/arch/s390/mm/init.c --- linux-2.4.0/arch/s390/mm/init.c Wed Nov 29 06:43:39 2000 +++ linux.ac/arch/s390/mm/init.c Fri Jan 5 00:00:32 2001 @@ -52,10 +52,10 @@ * data and COW. */ -pgd_t swapper_pg_dir[512] __attribute__ ((__aligned__ (4096))); -unsigned long empty_bad_page[1024] __attribute__ ((__aligned__ (4096))); -unsigned long empty_zero_page[1024] __attribute__ ((__aligned__ (4096))); -pte_t empty_bad_pte_table[1024] __attribute__ ((__aligned__ (4096))); +pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); +char empty_bad_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +pte_t empty_bad_pte_table[PTRS_PER_PTE] __attribute__((__aligned__(PAGE_SIZE))); static int test_access(unsigned long loc) { @@ -104,47 +104,6 @@ pte_clear(pte++); } -void __handle_bad_pmd(pmd_t *pmd) -{ - pmd_ERROR(*pmd); - pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table()); -} - -void __handle_bad_pmd_kernel(pmd_t *pmd) -{ - pmd_ERROR(*pmd); - pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table()); -} - -pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *) __get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (pte) { - invalidate_page(pte); - pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(pte); - pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(pte)+1024; - pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(pte)+2048; - pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(pte)+3072; - return pte + offset; - } - pte = get_bad_pte_table(); - pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(pte); - pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(pte)+1024; - pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(pte)+2048; - pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(pte)+3072; - return NULL; - } - free_page((unsigned long)pte); - if (pmd_bad(*pmd)) { - __handle_bad_pmd_kernel(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + offset; -} - pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) { unsigned long pte; @@ -167,10 +126,8 @@ return NULL; } free_page(pte); - if (pmd_bad(*pmd)) { - __handle_bad_pmd(pmd); - return NULL; - } + if (pmd_bad(*pmd)) + BUG(); return (pte_t *) pmd_page(*pmd) + offset; } @@ -180,7 +137,7 @@ if(pgtable_cache_size > high) { do { if(pgd_quicklist) - free_pgd_slow(get_pgd_fast()), freed++; + free_pgd_slow(get_pgd_fast()), freed += 2; if(pmd_quicklist) free_pmd_slow(get_pmd_fast()), freed++; if(pte_quicklist) @@ -245,6 +202,7 @@ unsigned long address=0; unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; unsigned long end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE); + static const int ssm_mask = 0x04000000L; /* unmap whole virtual address space */ @@ -283,8 +241,9 @@ /* enable virtual mapping in kernel mode */ __asm__ __volatile__(" LCTL 1,1,%0\n" " LCTL 7,7,%0\n" - " LCTL 13,13,%0" - : :"m" (pgdir_k)); + " LCTL 13,13,%0\n" + " SSM %1" + : : "m" (pgdir_k), "m" (ssm_mask)); local_flush_tlb(); @@ -378,6 +337,7 @@ val->sharedram = 0; val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); + val->totalhigh = 0; + val->freehigh = 0; val->mem_unit = PAGE_SIZE; - return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/mm/ioremap.c linux.ac/arch/s390/mm/ioremap.c --- linux-2.4.0/arch/s390/mm/ioremap.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/mm/ioremap.c Fri Jan 5 00:00:32 2001 @@ -33,8 +33,8 @@ printk("remap_area_pte: page already exists\n"); BUG(); } - set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | - _PAGE_DIRTY | _PAGE_ACCESSED | flags))); + set_pte(pte, mk_pte_phys(phys_addr, + __pgprot(_PAGE_PRESENT | flags))); address += PAGE_SIZE; phys_addr += PAGE_SIZE; pte++; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/tools/dasdfmt/dasdfmt.8 linux.ac/arch/s390/tools/dasdfmt/dasdfmt.8 --- linux-2.4.0/arch/s390/tools/dasdfmt/dasdfmt.8 Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/tools/dasdfmt/dasdfmt.8 Fri Jan 5 00:00:32 2001 @@ -1,74 +1,68 @@ -.TH DASDFMT 8 "Tue Jan 25 2000" -.UC 4 -.SH NAME -dasdfmt \- formatting of DSAD (ECKD) disk drives. -.SH SYNOPSIS -\fBdasdfmt\fR [-tvyV] [-b \fIblockSize\fR] [\fIblockRange\fI] - \fIdiskSpec\fR -.SH DESCRIPTION -\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it -for usage with Linux for S/390. \fBWARNING\fR: Incautious usage of -\fBdasdfmt\fR can result in \fBLOSS OF DATA\fR. - -.SH OPTIONS -.TP -\fB-t\fR -Disables any modification of the disk drive. \fBdasdfmt\fR just prints -out, what it \fBwould\fR do. - -.TP -\fB-v\fR -Increases verbosity. - -.TP -\fB-y\fR -Start formatting without further user-confirmation. - -.TP -\fB-V\fR -Print version number and exit. - -.TP -\fB-b\fR \fIblockSize\fR -Specify blocksize to be used. \fIblocksize\fR must be a positive integer -and always be a power of two. Due due some limitations in the driver, -it is \fBstrongly\fR recommended to use a \fIblockSize\fR of \fI4096\fR. - -.TP -\fIblockRange\fR -This parameter specifies the number of the first and last block to be -formatted. If this parameter is \fBomitted\fR, formatting the \fBwhole\fR disk -is assumed. The \fIblockRange\fR can be specified in two different formats: -.sp - \fB-s\fR \fIstartBlock\fR \fB-e\fR \fIendBlock\fR -.br -or -.br - \fB-r\fR \fIstartBlock\fR-\fIendBlock\fR -.sp -If \fIstartBlock\fR is omitted, block \fB0\fR is assumed. If -\fIendBlock\fR is omitted, the last block of the disk is assumed. - -.TP -\fIdiskSpec\fR -This parameter specified the device to be formatted. It also can be -given in two variants: -.sp - \fB-f\fR \fB/dev/dd\fR\fIX\fR -.br -or -.br - \fB-n\fR \fIdevnum\fR -.sp -The first form uses the commonly used -.SM UNIX -device notation where \fIX\fR is a single lowercase letter. -The second form uses simply the VM vdev number. - -.SH BUGS -None so far ;-) - -.SH AUTHOR -.nf -This man-page was written by Fritz Elfert -.fi +.TH DASDFMT 8 "Tue Jan 25 2000" +.UC 4 +.SH NAME +dasdfmt \- formatting of DSAD (ECKD) disk drives. +.SH SYNOPSIS +\fBdasdfmt\fR [-tvyLV] [-b \fIblockSize\fR] [-l \fIdiskLabel\fR] \fIdiskSpec\fR +.SH DESCRIPTION +\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it +for usage with Linux for S/390. \fBWARNING\fR: Incautious usage of +\fBdasdfmt\fR can result in \fBLOSS OF DATA\fR. + +.SH OPTIONS +.TP +\fB-t\fR +Disables any modification of the disk drive. \fBdasdfmt\fR just prints +out, what it \fBwould\fR do. + +.TP +\fB-v\fR +Increases verbosity. + +.TP +\fB-y\fR +Start formatting without further user-confirmation. + +.TP +\fB-L\fR +Omit the writing of a disk label after formatting. + +.TP +\fB-V\fR +Print version number and exit. + +.TP +\fB-b\fR \fIblockSize\fR +Specify blocksize to be used. \fIblocksize\fR must be a positive integer +and always be a power of two. Due due some limitations in the driver, +it is \fBstrongly\fR recommended to use a \fIblockSize\fR of \fI4096\fR. + +.TP +\fB-l\fR \fIdiskLabel\fR +Specify the label to be written to disk after formatting. If no label is +specified, a sensible default is used. \fIdiskLabel\fR is interpreted as +ASCII string and is automatically converted to EBCDIC. + +.TP +\fIdiskSpec\fR +This parameter specified the device to be formatted. It also can be +given in two variants: +.sp + \fB-f\fR \fB/dev/dasd\fR\fIX\fR +.br +or +.br + \fB-n\fR \fIdevnum\fR +.sp +The first form uses the commonly used +.SM UNIX +device notation where \fIX\fR is a single lowercase letter. +The second form uses simply the device number. + +.SH BUGS +None so far ;-) + +.SH AUTHOR +.nf +This man-page was written by Fritz Elfert +.fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.4.0/arch/s390/tools/dasdfmt/dasdfmt.c linux.ac/arch/s390/tools/dasdfmt/dasdfmt.c --- linux-2.4.0/arch/s390/tools/dasdfmt/dasdfmt.c Fri May 12 19:41:45 2000 +++ linux.ac/arch/s390/tools/dasdfmt/dasdfmt.c Fri Jan 5 00:00:32 2001 @@ -12,6 +12,8 @@ * detect non-switch parameters ("dasdfmt -n 170 XY") and complain about them */ +/* #define _LINUX_BLKDEV_H */ + #include #include #include @@ -22,22 +24,29 @@ #include #include #include +#include #include #include #include -#include "../../../drivers/s390/block/dasd.h" /* uses DASD_PARTN_BITS */ #define __KERNEL__ /* we want to use kdev_t and not have to define it */ #include #undef __KERNEL__ +#include +#include +#include + #define EXIT_MISUSE 1 #define EXIT_BUSY 2 #define TEMPFILENAME "/tmp/ddfXXXXXX" #define TEMPFILENAMECHARS 8 /* 8 characters are fixed in all temp filenames */ -#define IOCTL_COMMAND 'D' << 8 #define SLASHDEV "/dev/" #define PROC_DASD_DEVICES "/proc/dasd/devices" +/* _PATH_MOUNTED is /etc/mtab - /proc/mounts does not show root-fs correctly */ +#define PROC_MOUNTS _PATH_MOUNTED +#define PROC_SWAPS "/proc/swaps" #define DASD_DRIVER_NAME "dasd" +#define LABEL_LENGTH 10 #define PROC_LINE_LENGTH 80 #define ERR_LENGTH 80 @@ -66,24 +75,108 @@ ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ "is in invalid format\n",prog_name);} -typedef struct { - int start_unit; - int stop_unit; - int blksize; -} format_data_t; - -char prog_name[]="dasd_format"; +char *prog_name;/*="dasdfmt";*/ char tempfilename[]=TEMPFILENAME; +__u8 _ascebc[256] = +{ + /*00 NUL SOH STX ETX EOT ENQ ACK BEL */ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, + /*08 BS HT LF VT FF CR SO SI */ + /* ->NL */ + 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /*10 DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, + /*18 CAN EM SUB ESC FS GS RS US */ + /* ->IGS ->IRS ->IUS */ + 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F, + /*20 SP ! " # $ % & ' */ + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, + /*28 ( ) * + , - . / */ + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + /*30 0 1 2 3 4 5 6 7 */ + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + /*38 8 9 : ; < = > ? */ + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + /*40 @ A B C D E F G */ + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + /*48 H I J K L M N O */ + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + /*50 P Q R S T U V W */ + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + /*58 X Y Z [ \ ] ^ _ */ + 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, + /*60 ` a b c d e f g */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /*68 h i j k l m n o */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + /*70 p q r s t u v w */ + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + /*78 x y z { | } ~ DL */ + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, + /*80*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*88*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*90*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*98*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*A0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*A8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*B0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*B8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*C0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*C8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*D0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*D8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*E0 sz */ + 0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*E8*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*F0*/ + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + /*F8*/ + 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF +}; + +void convert_label(char *str) +{ + int i; + for (i=0;i \n\n", - prog_name); - printf(" where is either\n"); - printf(" -s start_track -e end_track\n"); +#ifdef RANGE_FORMATTING + printf("Usage: %s [-htvyLV] [-l