diff -uNr --exclude=CVS linux-2.4.9-ac10/Documentation/Configure.help linuxppc64_2_4/Documentation/Configure.help
--- linux-2.4.9-ac10/Documentation/Configure.help Thu Sep 6 14:11:16 2001
+++ linuxppc64_2_4/Documentation/Configure.help Fri Sep 14 10:42:50 2001
@@ -179,6 +179,14 @@
from Motorola. The Linux PowerPC port has a home page at
.
+PowerPC64 processor
+CONFIG_PPC64
+ The PowerPC architecture was designed for both 32 bit and 64 bit
+ processor implementations. 64 bit PowerPC processors are in many
+ ways a superset of their 32 bit PowerPC cousins. Each 64 bit PowerPC
+ processor also has a 32 bit mode to allow for 32 bit compatibility.
+ The home of the PowerPC 64 Linux project is at
+
Motorola 68K processors
CONFIG_M68K
The Motorola 68K microprocessors are now obsolete, having been
@@ -14337,6 +14345,13 @@
hard drives and ADFS-formatted floppy disks. This is experimental
codes, so if you're unsure, say N.
+JFS filesystem support
+CONFIG_JFS_FS
+ This is a port of IBM's Journaled Filesystem . More information is
+ available in the file Documentation/filesystems/jfs.txt.
+
+ If you do not intend to use the JFS filesystem, say N.
+
/dev/pts file system for Unix98 PTYs
CONFIG_DEVPTS_FS
You should say Y here if you said Y to "Unix98 PTY support" above.
@@ -19954,23 +19969,63 @@
Select PowerMac/PReP/MTX/CHRP if configuring for any of the above.
Select Gemini if configuring for a Synergy Microsystems' Gemini
- series Single Board Computer. More information is available at:
- .
+ series Single Board Computer. More information is available at:
+
+
+ Select APUS if configuring for a PowerUP Amiga. More information is
+ available at:
+
+# Choice: i or p
+Platform support
+CONFIG_PPC_ISERIES
+ Linux runs on certain models of the IBM AS/400, now known as the
+ IBM iSeries. Generally if you can run LPAR (Logical Partitioning)
+ on your iSeries you can run Linux in a partition on your machine.
+
+ Linux also runs on most models of IBM pSeries hardware. (pSeries
+ used to be known as the RS/6000)
+
+ If you have an iSeries and want to run Linux in a partition,
+ select the iSeries option to build your kernel.
+
+ If you have a pSeries and want to run Linux, select pSeries
+ as the option to build your kernel.
+
+ See for exact model information to see what
+ can run the 64 bit PowerPC kernel.
+
+ iSeries Linux information from IBM can be found at:
+
+
+ pSeries Linux information from IBM can be found at:
+
- Select APUS if configuring for a PowerUP Amiga. More information is
- available at: .
+ Project information can be found at:
+
+
+
+Platform support
+CONFIG_PPC_PSERIES
+ Linux runs on most models of IBM pSeries hardware. (pSeries used
+ to be known as the RS/6000)
+
+ See for exact model information for the
+ 64 bit PowerPC kernel.
+
+ pSeries Linux information from IBM can be found at:
+
Synergy-Gemini
CONFIG_GEMINI
Select Gemini if configuring for a Synergy Microsystems' Gemini
series Single Board Computer. More information is available at:
- .
+
Amiga-Apus
CONFIG_APUS
Select APUS if configuring for a PowerUP Amiga.
More information is available at:
- .
+
AltiVec Kernel Support
CONFIG_ALTIVEC
@@ -20213,19 +20268,33 @@
Support for EST8260
CONFIG_EST8260
The EST8260 is a single-board computer manufactured by Wind River
- Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
- the MPC8260. Wind River Systems has a website at
- , but the EST8260 cannot be found on it
+ Systems Inc. (formerly Embedded Support Tools Corp.) and based
+ on the MPC8260. Wind River Systems has a website at
+ , but the EST8260 cannot be found on it
and has probably been discontinued or rebadged.
+Support for Large Memory
+CONFIG_MSCHUNKS
+ MsChunks stands for Main Store Chunks and specifically allows the
+ 64 bit PowerPC Linux kernel to optimize for machines with sparse
+ discontiguous memory. iSeries kernels need to have this on.
+ It is recommended that for pSeries hardware that you answer Y.
+
+AltiVec support
+CONFIG_ALTIVEC
+ Say Y here to compile in support for Motorola AltiVec boards. The
+ AltiVec board is baced on the MPC7400 embedded version of the
+ PowerPC and adds a SIMD vector-processing unit. Product information
+ at .
+
ADB raw keycode support
CONFIG_MAC_ADBKEYCODES
This provides support for sending raw ADB keycodes to console
devices. This is the default up to 2.4.0, but in future this may be
- phased out in favor of generic Linux keycodes. If you say Y here,
+ phased out in favor of generic Linux keycodes. If you say Y here,
you can dynamically switch via the
/proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
- sysctl and with the "keyboard_sends_linux_keycodes=" kernel
+ sysctl and with the "keyboard_sends_linux_keycodes=" kernel
argument.
If unsure, say Y here.
@@ -20233,8 +20302,8 @@
Mouse button 2+3 emulation support
CONFIG_MAC_EMUMOUSEBTN
This provides generic support for emulating the 2nd and 3rd mouse
- button with keypresses. If you say Y here, the emulation is still
- disabled by default. The emulation is controlled by these sysctl
+ button with keypresses. If you say Y here, the emulation is still
+ disabled by default. The emulation is controlled by these sysctl
entries:
/proc/sys/dev/mac_hid/mouse_button_emulation
/proc/sys/dev/mac_hid/mouse_button2_keycode
@@ -22955,6 +23024,11 @@
CONFIG_XMON
Include in-kernel hooks for the xmon kernel monitor/debugger
supported by the PPC port.
+
+Include realtime debugging
+CONFIG_PPCDBG
+ Include in-kernel PowerPC 64 information hooks that may be turned on/off
+ in real time.
Include kgdb kernel debugger
CONFIG_KWDB
diff -uNr --exclude=CVS linux-2.4.9-ac10/Documentation/cachetlb.txt linuxppc64_2_4/Documentation/cachetlb.txt
--- linux-2.4.9-ac10/Documentation/cachetlb.txt Thu Sep 6 14:05:19 2001
+++ linuxppc64_2_4/Documentation/cachetlb.txt Fri Sep 7 06:23:33 2001
@@ -260,8 +260,9 @@
Here is the new interface:
- void copy_user_page(void *to, void *from, unsigned long address)
- void clear_user_page(void *to, unsigned long address)
+ void copy_user_page(struct page *to, struct page *from,
+ unsigned long address)
+ void clear_user_page(struct page *to, unsigned long address)
These two routines store data in user anonymous or COW
pages. It allows a port to efficiently avoid D-cache alias
@@ -279,6 +280,11 @@
If D-cache aliasing is not an issue, these two routines may
simply call memcpy/memset directly and do nothing more.
+
+ There are default versions of these procedures supplied in
+ include/linux/highmem.h. If a port does not want to use the
+ default versions it should declare them and define the symbol
+ __HAVE_ARCH_USER_PAGE in include/asm/page.h.
void flush_dcache_page(struct page *page)
diff -uNr --exclude=CVS linux-2.4.9-ac10/Documentation/filesystems/00-INDEX linuxppc64_2_4/Documentation/filesystems/00-INDEX
--- linux-2.4.9-ac10/Documentation/filesystems/00-INDEX Thu Sep 6 14:05:13 2001
+++ linuxppc64_2_4/Documentation/filesystems/00-INDEX Thu Sep 13 14:29:38 2001
@@ -22,6 +22,8 @@
- info and mount options for the OS/2 HPFS.
isofs.txt
- info and mount options for the ISO 9660 (CDROM) filesystem.
+jfs.txt
+ - info and mount options for the JFS filesystem.
ncpfs.txt
- info on Novell Netware(tm) filesystem using NCP protocol.
ntfs.txt
diff -uNr --exclude=CVS linux-2.4.9-ac10/Documentation/filesystems/changelog.jfs linuxppc64_2_4/Documentation/filesystems/changelog.jfs
--- linux-2.4.9-ac10/Documentation/filesystems/changelog.jfs Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/Documentation/filesystems/changelog.jfs Thu Sep 13 14:31:38 2001
@@ -0,0 +1,594 @@
+IBM's Journaled File System (JFS) for Linux version 1.0.4
+Team members
+Steve Best sbest@us.ibm.com
+Dave Kleikamp shaggy@us.ibm.com
+Barry Arndt barndt@us.ibm.com
+
+
+Release August 31, 2001 (version 1.0.4)
+
+This is our forty-second release of IBM's Enterprise JFS technology port to Linux.
+Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001,
+Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001.
+
+The first drop on February 2, 2000 (jfs-0.0.1.tar.gz) had the following
+functionality (enough to allow other developers to evaluate and potentially
+contribute to this project):
+
+ - MKFS functional and able to format an existing or newly created partition for JFS.
+ - mount/unmount functional
+ - able to view the self(.) and parent (..) directories entries.
+
+The second drop on February 28, 2000 (jfs-0.0.2.tar.gz) had fixes for MKFS and the
+following utilities logredo, xchkdmp, xpeek are functional. The file system was able
+to mkdir, create files and directories were working (and rm, rmdir).
+
+The third drop on March 24, 2000 (jfs-0.0.3.tar.gz) provided read and write capability
+for the file system. Also, support for hard and soft links are functional.
+
+The fourth drop on March 29,2000 (jfs-0.0.4.tar.gz) provided rename capability for
+the file system and fixes for write problems.
+
+The fifth drop on April 6, 2000 (jfs-0.0.5.tar.gz) provided mknod capability for the
+file system.
+
+The sixth drop on April 21, 2000 (jfs-0.0.6.tar.gz) provided fixes for the file system
+and utilities.
+
+The seventh drop on May 11, 2000 (jfs-0.0.7.tar.gz) provided changes to the file system
+to be able to work on the development kernel 2.3.99-pre6. Drop 7 contains fixes for the
+file system to be built within the kernel.
+
+The eighth drop on June 20, 2000 (jfs-0.0.8.tar.gz) provided fixes for the file system
+and changes to the file system to be able to work on the development kernel 2.4.0-test1-ac21.
+In the utility area: fsck and logdump are functional.
+
+The ninth drop on July 13, 2000 (jfs-0.0.9.tar.gz) has the meta-data of the file system
+using the page cache. In the utility area: fixes for fsck.jfs and xpeek are included.
+
+The tenth drop on August 11, 2000 provided fixes for the file system
+and changes to the file system to be able to work on the development kernel 2.4.0-test5.
+In the utility area: fixes for fsck.jfs are included. The utility portion of extendfs has
+been ported (still need to port the file system portion for extendfs). Man pages have
+been written for the utilities. The compiler warnings have been removed from all of the
+utilities.
+
+The eleventh drop on September 1, 2000 provided fixes for the file system
+and changes to the file system to be able to work on the development kernel 2.4.0-test7.
+The utility portion of defrag has been ported (still need to port the file system portion
+for defrag).
+
+The twelfth drop on September 15, 2000 (jfs-0.0.12.tar.gz) provided the Transaction
+Manager Log I/O routines.
+
+The thirteenth drop on September 29, 2000 (jfs-0.0.13.tar.gz) provided case-sensitive
+support. In the utility area: fsck.jfs has the support for block/character special files.
+Note: The JFS partition must be formatted/reformatted using mkfs.jfs created by drop 13
+for case-sensitive to work.
+
+The fourteenth drop on October 4, 2000 (jfs-0.0.14.tar.gz) included a fix to the file
+system for not mounting a JFS partition if the size of the partition is > 4G on 2.2.x
+series of the kernel.
+
+The fifteenth drop on October 9, 2000 (jfs-0.0.15.tar.gz) included the Transaction
+Manager routines (Initialize, Begin, Locks, End). The file system has fixes and
+changes to the file system to be able to work on the development kernel 2.4.0-test9.
+The utility xchklog has been ported.
+
+The sixteenth drop on October 27, 2000 (jfs-0.0.16.tar.gz) included the Transaction
+Manager routines (Commit, Buffer Management, Abort). The file system and utilities
+have fixes included.
+
+The seventeenth drop on November 10, 2000 (jfs-0.0.17.tar.gz) has the transaction
+sub operations back into the file system operations. The file system is now journaling
+appropriate file system operations. The file system is temporary doing synchronous logging
+(which slows down operations that are logged) to make sure that the transaction processing
+is right. Asynchronous logging will be added shortly. The file system has fixes and changes
+to the file system to be able to work on the development kernel 2.4.0-test10.
+
+The eighteenth drop on November 15, 2000 (jfs-0.0.18.tar.gz) included fixes to the file
+system.
+
+The nineteenth drop on December 4, 2000 (jfs-0.0.19.tar.gz) is now doing asynchronous
+logging. The file system has fixes and changes to the file system to be able to work
+on the development kernel 2.4.0-test11.
+
+The twentieth drop on December 8, 2000 (jfs-0.1.0.tar.gz beta) included fixes to the file
+system.
+
+The twenty-first drop on December 14, 2000 (jfs-0.1.1.tar.gz) included a fsck fix
+to handle sparse files correctly. The file system has fixes and changes to the file
+system to be able to work on the development kernel 2.4.0-test12 and 2.2.18 kernel.
+
+The twenty-second drop on January 5, 2001 (jfs-0.1.2.tar.gz) included fixes to the
+file system. The file system has changes to able to work on the 2.4.0 kernel.
+
+The twenty-third drop on January 12, 2001 (jfs-0.1.3.tar.gz) included fixes to the
+file system. Fsck now supports fifo correctly.
+
+The twenty-fourth drop on January 26, 2001 (jfs-0.1.4.tar.gz) included fixes to the
+file system. The new feature in the file system is "Lazy Commit" which increases
+performance while going asynchronous logging. The main makefile for the utilities
+now has an install option.
+
+The twenty-fifth drop on February 7, 2001 (jfs-0.1.5.tar.gz) included fixes to the
+file system.
+
+The twenty-sixth drop on February 26, 2001 (jfs-0.1.6.tar.gz) included fixes to the
+file system. The log manager no longer uses the page cache for log pages, this
+eliminates dead-locks that were occurring in the log manager. The file system has
+general work done to remove SMP dead-lock problems. Fsck now supports default values
+passed by fstab correctly.
+
+The twenty-seventh drop on March 7, 2001 (beta 2) (jfs-0.2.0.tar.gz) included fixes to the
+file system. This drop contains jfsprogs.spec that can be used to create RPM for the
+JFS utilities. The file system has general work done to remove SMP and UP hang related problems.
+The file system performance has been increased by changes to extent inode cache.
+
+The twenty-eighth drop on March 21, 2001 (jfs-0.2.1.tar.gz) included fixes to the
+file system. The file system has been changed to use standard types.
+
+The twenty-ninth drop on April 2, 2001 (jfs-0.2.2.tar.gz) included fixes to the
+file system. The utilities have been changed to use standard types.
+
+The thirtieth drop on April 30, 2001 (jfs-0.3.0.tar.gz) included fixes to the
+file system. The rest of the utilities have been changed to use standard types.
+Both the file system and the utilities have been changed to use endian macros,
+so that JFS will now store the meta-data as little endian when running on all
+architectures, with this change you must re-format all of the JFS partitions
+using the new mkfs.jfs included in this drop, if you are running on a big-endian system.
+
+The thirty-first drop on May 9, 2001 (jfs-0.3.1.tar.gz) included fixes to the file
+system and the utilities.
+
+The thirty-second drop on May 18, 2001 (jfs-0.3.2-patch.tar.gz) included fixes to the file
+system and the utilities.
+
+The thirty-third drop on May 25, 2001 (jfs-0.3.3-patch.tar.gz) included fixes to the file
+system and the utilities.
+
+The thirty-fourth drop on June 8, 2001 (jfs-0.3.4-patch.tar.gz) included fixes to the
+file system and the utilities.
+
+The thirty-fifth drop on June 15, 2001 (jfs-0.3.5-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The thirty-sixth drop on June 22, 2001 (jfs-0.3.6-patch.tar.gz) includes fixes to the
+file system and utilities. The change made to the file system to fix the rm -rf problem
+is a disk layout change and with this change you must re-format all of the JFS partitions
+using the new mkfs.jfs included in this drop to have the rm -rf problem fixed.
+
+
+The thirty-seventh drop on June 25, 2001 (jfs-0.3.7-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The thirty-eighth drop on June 28, 2001 (jfs-1.0.0-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The thirty-ninth drop on July 10, 2001 (jfs-1.0.1-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The fortieth drop on August 3, 2001 (jfs-1.0.2-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+The forty-first drop on August 20, 2001 (jfs-1.0.3-patch.tar.gz) includes fixes to the
+file system and utilities.
+
+
+The forty-second drop on August 31, 2001 (jfs-2.2-1.0.4-patch.tar.gz or
+jfs-2.4-1.0.4-patch.tar.gz) includes fixes to the file system and utilities.
+
+Drop 42 has the temporary restriction that the block size must be 4K. MKFS.jfs defaults
+the block size to 4K.
+
+
+JFS today:
+
+
+- Utilities:
+ Function in drop 1
+ - MKFS.JFS builds on 2.2.12
+ - MKFS successfully formats a new partition for JFS
+
+ Function and Fixes in drop 2
+ - MKFS supports all parameters now
+ - MKFS has fixes from release pre-alpha 0.0.1
+ mkfs.jfs results in segmentation fault if no arguments are specified
+ mkfs.jfs hangs on invocation
+
+ - XPEEK, utility to PEEK and POKE JFS on-disk data/structures
+
+ Function and Fixes in drop 5
+ - MKFS.jfs has a fix to support -l option correctly.
+
+ Function and Fixes in drop 6
+ - libfs has compiler warning fixes and a bug fix
+
+ Function in drop 8
+ - fsck.jfs successfully checks and repairs a jfs partition
+ - logdump, utility that dumps the contents of the journal log.
+
+ Function and Fixes in drop 9
+ - fixes for fsck.jfs and xpeek have been done.
+
+ Function and Fixes in drop 10
+ - fixes for fsck.jfs
+ - man pages for utilities
+ - extendfs utility part has been ported (still need to port FS portion)
+ - compiler warnings have been removed.
+
+ Function and Fixes in drop 11
+ - defrag utility part has been ported (still need to port FS portion)
+
+ Function and Fixes in drop 13
+ - fsck.jfs supports block special files and character special files (Jitterbug problem #28)
+
+ Function and Fixes in drop 15
+ - ported xchklog utility, extracts a log from fsck.
+
+ Function and Fixes in drop 16
+ - fixes for fsck.jfs to handle case-sensitive support correctly (Jitterbug problem #36)
+ - cleanup changes for the utilities
+
+ Function and Fixes in drop 18
+ - cleanup changes for the utilities
+
+ Function and Fixes in drop 21
+ - fix in fsck to handle sparse files correctly
+
+ Function and Fixes in drop 23
+ - fix in fsck to handle fifo correctly
+
+ Function and Fixes in drop 24
+ - man pages updates for the utilities
+ - install option for utilities
+
+ Function and Fixes in drop 26
+ - man page updates for fsck
+ - fsck now supports default options passed by fstab correctly
+
+ Function and Fixes in drop 27
+ - new jfsprogs.spec file
+ - fix in fsck for hard links
+ - fix for unicode conversion problem
+
+ Function and Fixes in drop 29
+ - cleanup changes for the utilities
+ - Code cleanup to use standard types
+
+ Function and Fixes in drop 30
+ - added endian macros support
+ - Code cleanup to use standard types (part 2)
+ - mkfs now clears out the 1st 4k bytes of the partition
+
+ Function and Fixes in drop 31
+ - completed endian macros support needed for xpeek
+ - added socket support for fsck
+ - minor bug fixes
+
+ Function and Fixes in drop 32
+ - Remove the warning message from fsck when partition is mounted read-only
+
+ Function and Fixes in drop 33
+ - Fix fsck to handle mount read-only correctly
+ - Fix top level utilities makefile to be able to easily overide version of gcc compiler
+ - Man pages are now available in html format
+
+ Function and Fixes in drop 34
+ - fsck fix to handle pre-existing lost+found sub dir
+
+ Function and Fixes in drop 35
+ - updated fsck error handling
+ - updated mkfs config options and the man page for fsck
+
+ Function and Fixes in drop 36
+ - Fixed jitterbug # 10 rm -rf fails on a big directory
+
+ Function and Fixes in drop 38
+ - Fixed small logredo problem
+
+ Function and Fixes in drop 39 (1.0.1)
+ - Updated jfsprogs.spec file make it work on more distros
+ - Add force option to mkfs so the confirmation message isn't displayed
+ - Fixed fsck to handle index table on the root directory.
+ - Fixed error message displayed when partition was just created and haven't rebooted (jitterbug 130)
+ - Correctly place the built utilities in /sbin vs. /usr/sbin when using the make install
+ option.
+
+ Note: If you have used the make install option to copy over the utilities from a
+ previous release then you should remove the following JFS utilities (fsck.jfs, logdump,
+ logredo, mkfs.jfs, xchkdmp, xchklog, and xpeek) that could be in /usr/sbin. This release
+ of make install places the utilities in the correct location which is /sbin.
+
+ Function and Fixes in drop 40 (1.0.2)
+ - Fixed mkfs to display the correct error message if device name is not valid
+ or missing
+ - gzip the man pages and place /usr/share/man/man8
+ - Fixed mkfs to properly setup buf_ai (caused Bus error with mkfs on SPARC Linux)
+ - Fixed fsck to display path correctly
+
+ Function and Fixes in drop 41 (1.0.3)
+ - Fixed compiler warnings on 64 bit systems
+ - Created jfsutils package
+
+ Function and Fixes in drop 42 (1.0.4)
+ - Fixed typecast problem causing intermittent fsck failures on 64 bit hardware (jitterbug 159)
+ - Fixed pointer calculation problem causing intermittent fsck failures on 64 bit hardware
+ - Fixed compiler warnings on s/390 and IA64
+ - Fixed structure size mismatch between file system and utilities causing fsck problems when
+ large numbers of inodes are used
+ - Fixed seg fault in fsck when logging path lengths greater than 512 characters
+ - Fixed fsck printf format errors
+
+
+- JFS:
+ Function in drop 1
+ - builds on 2.2.12
+ - successfully MOUNTs & UMOUNTs
+ - limited READ capability (i.e. LS is operational)
+ - other system commands (i.e. DF, CHOWN, CHMOD, etc. working limited)
+
+ Function and Fixes in drop 2
+ - Write capabilities are operational
+ - MKDIR
+ - CREATE file
+ - RMDIR
+ - RM
+ - Problems fixed from release pre-alpha 0.0.1
+ using 2.2.14 jfs_imap.c:3004: `event' undeclared (first use in this function)
+
+ Function and Fixes in drop 3
+ - WRITE a file
+ - READ a file
+ - Support for hard and soft links
+
+ Function and Fixes in drop 4
+ - MV
+ - Executables can now be started from a jfs partition
+ - Problems while writing files have been fixed
+
+ Function and Fixes in drop 5
+ - added support for special files (mknod)
+ - alpha changes have been included
+
+ Function and Fixes in drop 6
+ - Jitterbug problem 9 du output is incorrect on jfs
+ - Jitterbug problem 11 unresolved symbol jfs_rwlock_lock on SMP build
+
+ Function and Fixes in drop 7
+ - moved JFS upto the 2.3.x development kernel (2.3.99-pre6)
+ - Jitterbug problem 14 can't build JFS within the kernel
+
+ Function and Fixes in drop 8
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test1-ac21)
+ - Jitterbug problem 17 undefined: jfs_rdwrlock_lock
+ - PowerPC build problem
+
+ Function and Fixes in drop 9
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test3)
+ - moved meta-data from buffer cache to page cache
+ - fixes for the file system are included
+
+ Function and Fixes in drop 10
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test5)
+ - fixes for the file system are included
+
+ Function and Fixes in drop 11
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test7)
+ - fixes for the file system are included
+ - start of journaling code has been included (jfs_txnmgr.h)
+ - WIP of log manager (jfs_logmgr.c)
+
+ Function and Fixes in drop 12
+ - Transaction Manager Log I/O -> Write log records is functional
+
+ Function and Fixes in drop 13
+ - case-sensitive support has been added
+
+ Function and Fixes in drop 14
+ - JFS mount error 22 is fixed (Jitterbug problem #30)
+
+ Function and Fixes in drop 15
+ - Following Transaction Manager routines are functional
+ Initialize -> Initialize transaction manager
+ Begin -> Start a transaction
+ Locks -> Acquire/release locks
+ End -> End a transaction
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test9)
+ - Fixed 2.2.x series block write problem.
+
+ Function and Fixes in drop 16
+ - Following Transaction Manager routines are functional
+ Commit -> Commit the transaction
+ Buffer Management -> Update inode, directory, extent
+ Abort -> Stop the commit from occurring
+ - File System build problem on 2.2.x series of the kernel (Jitterbug #35)
+ - Fixed case-sensitive bug in the filesystem (Jitterbug #36)
+
+
+ Function and Fixes in drop 17
+ - Added transaction sub operations back into the file system operations.
+ - The file system is now journaling appropriate file system operations.
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test10)
+
+ Function and Fixes in drop 18
+ - symlink fix
+ - inode corruption problem
+
+ Function and Fixes in drop 19
+ - Added asynchronous logging support back into the file system.
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test11)
+ - Fixes to transaction related hang problems.
+
+ Function and Fixes in drop 20
+ - Fix to remove memory on module cleanup
+
+ Function and Fixes in drop 21
+ - Fix so fsck doesn't report the message
+ Secondary file/directory allocation structure(2) is not a correct redundant copy of primary structure.
+ - Fix for setup of finish_aync_io
+ - moved JFS upto the 2.4.0 development kernel (2.4.0-test12)
+ - moved JFS upto the 2.2.18 kernel
+
+ Function and Fixes in drop 22
+
+ - moved JFS upto the 2.4.0 kernel
+ - Fix to do transaction processing for mknod correctly
+ - Fix for spinlock.h needed on 2.2.18 ppc
+
+ Function and Fixes in drop 23
+ - Fix for undefined BUG() in 2.2.x series
+ - Fix for 2.2 kernels, struct pipe_inode_info overlays the file system dependent portion of the inode structure.
+
+ Function and Fixes in drop 24
+ - rmmod jfs fix
+ - Implemented "Lazy Commit" - asynchronous logging enhancement to increase performance
+ - Removed ino_t from on-disk structures (fixes a mount problem)
+
+ Function and Fixes in drop 25
+ - Fix for deadlocks by putting IWRITE_LOCK/UNLOCK within jfs_delete_inode
+ - Fix to handle removing a link to an inode that isn't the last link.
+ - Fixes to general transaction processing SMP related hangs.
+
+ Function and Fixes in drop 26
+ - Fix for file writes on 2.2.x series of the kernel
+ - Change to log pages, so they no longer use the page cache.
+ - Fixes to general transaction processing SMP related dead-lock problems
+
+ Function and Fixes in drop 27
+ - Report error on read_metapage failure in jfs_readlink
+ - Report correct error in jfs_lookup if VFS fails to locate the inode
+ - Fix for a buffer overrun problem in jfs_readlink when compiled for linux-2.2
+ - Fix to support fsync call correctly (jitterbug #57)
+ - Fixes to general SMP related dead-lock problems
+ - Fix to define BUG() if 2.2 and !i386
+ - Fixes to general UP related hangs
+ - Changes to handling the inode extent cache increase the performance of the file system
+
+ Function and Fixes in drop 28
+ - Added ifdef IS_KIOBUFIO so JFS will be if kiobufs is in the kernel. Kiobufs has changed
+ the # of parameters for generic_make_request()
+ - Make jfsFYI a module parameter
+ insmod jfs.o jfsFYI=1 will turn on JFS FYI messages without having to recompile this
+ option is only supported on the 2.4.x kernel level.
+ - Defines cleanup_module() in terms of exit_jfs_fs()
+ - Fix to jfs_read_super, if get_empty_inode returns NULL cleanup correctly
+ - Code cleanup to use standard types
+
+
+ Function and Fixes in drop 29
+ - Fix for assert(iagp->wmap[extno] & mask); (line #2875) in jfs_imap while running dbench
+ - Fixed hang on scsi
+ - added /proc/fs/jfs/jfsFYI (2.4.* kernels only)
+ echo 1 > /proc/fs/jfs/jfsFYI ; Turns on very verbose output to syslog
+ echo 0 > /proc/fs/jfs/jfsFYI ; Turns it back off
+
+ Notes:
+ - IMPORTANT: If building jfs.o as a module on 2.2.* kernels, you will have to rebuild and
+ install the kernel to add wake_up_process to ksyms.c. Not needed on 2.4.* kernels.
+
+ Function and Fixes in drop 30
+ - Added endian macros support
+ - Fixed dbench hang
+ - jfs fails SPEC SFS validation on both NFSv2/NFSv3, fix to not add null-terminator to the symlink
+ value and accounting for it in the size.
+ - Fixed a bug where a casting of a 32 bit block # wasn't correct when a 64 bit value is needed.
+ xtLookup messages where display in the /var/log/messages (i.e of a message is below)
+ xtLookup: lstart (0x80000) >= size (0x80000)
+
+ Notes: release 0.3.0 requires a re-format of the JFS partition, if the system architecture is
+ big-endian (i.e. s/390, PowerPC, etc.)
+
+ Function and Fixes in drop 31
+ - Removed max hard links check (showed up during cp -a /usr /jfs/usr)
+ - Fixed inode writing hang could have showed up running (dbench, iozone, etc),
+ the change was to prevent a deadlock during inode writing.
+
+ Function and Fixes in drop 32
+ - Fix for assert(mp->count) jfs_metapage.c 675! report as hardlink problem in drop 31 (dtDeleteUp
+ was discarding the wrong metapage_t.
+ - Fix seg fault problem while creating hard links.
+ - Fixed dbench hang do to transaction locks not being freed.
+ - Added support to correctly handle read-only and remounting the file system.
+
+ Function and Fixes in drop 33
+
+ - Fixed statfs call to return the maximum number of inodes that JFS could allocate. (problem
+ reported as rpm exits with a (x) inodes needed message without installing the package).
+ - Fix to handle a case where a inode wasn't getting written to disk.
+ - Increase the performance of unlinking files.
+ - Fix to null terminate symlinks.
+ - General SMP fixes.
+
+ Function and Fixes in drop 34
+
+ - Fixed to remove a hang waiting on inode (jitterbug #73)
+ - Fixed dbench hang on SMP 8-way
+ - Fixed a log sync problem, improved performance with this fix
+
+ Function and Fixes in drop 35
+ - Increase the performance of unlinking files, most unlinks are done asynchronously now
+ - Fixed "XT_GETPAGE: xtree page corrupt" during creating files on nfs mounted partition
+
+ Function and Fixes in drop 36
+ - Fixed jitterbug # 10 rm -rf fails on a big directory
+
+ Notes: release 0.3.6 requires a re-format of the JFS partition, for the rm -rf problem
+ to be fixed.
+
+ Function and Fixes in drop 37
+ - Fixed find_entry called with index = 0 or 1 (jitterbug #126)
+ - Fixed the rm -rf case where if files weren't created sequential
+ then the rm -rf wasn't working correctly
+
+
+ Notes: If you used release 0.3.6 please re-format all JFS partitions, for the rm -rf problem
+ to be fixed.
+
+ Function and Fixes in drop 38
+ - Fixed some general log problems
+
+ Function and Fixes in drop 39 (1.0.1)
+ - Fixed hang during copying files on 2.2.x series
+ - Fixed TxLock compile problem
+ - Fixed to correctly update the number of blocks for directories (this was causing the FS
+ to show fsck error after compiling mozilla).
+ - Fixed to prevent old data from being written to disk from the page cache.
+
+ Function and Fixes in drop40 (1.0.2)
+ - Fixed multiple truncate hang
+ - Fixed hang on unlink a file and sync happening at the same time
+ - Improved handling of kmalloc error conditions
+ - Fixed hang in blk_get_queue and SMP deadlock: bh_end_io call generic_make_request
+ (jitterbug 145 and 146)
+ - stbl was not set correctly set in dtDelete
+ - changed trap to printk in dbAllocAG to avoid system hang
+
+ Function and Fixes in drop41 (1.0.3)
+ - Patch to move from previous release to latest release needs to update the version number in super.c
+ - Jitterbug problems (134,140,152) removing files have been fixed
+ - Set rc=ENOSPC if ialloc fails in jfs_create and jfs_mkdir
+ - Fixed jfs_txnmgr.c 775! assert
+ - Fixed jfs_txnmgr.c 884! assert(mp->nohomeok==0)
+ - Fix hang - prevent tblocks from being exhausted
+ - Fix oops trying to mount reiserfs
+ - Fail more gracefully in jfs_imap.c
+ - Print more information when char2uni fails
+ - Fix timing problem between Block map and metapage cache - jitterbug 139
+ - Code Cleanup (removed many ifdef's, obsolete code, ran code through indent) Mostly 2.4 tree
+ - Split source tree (Now have a separate source tree for 2.2, 2.4, and jfsutils)
+
+ Function and Fixes in drop42 (1.0.4)
+ - Fixed compiler warnings in the FS when building on 64 bits systems
+ - Fixed deadlock where jfsCommit hung in hold_metapage
+ - Fixed problems with remount
+ - Reserve metapages for jfsCommit thread
+ - Get rid of buggy invalidate_metapage & use discard_metapage
+ - Don't hand metapages to jfsIOthread (too many context switches) (jitterbug 125, bugzilla 238)
+ - Fix error message in jfs_strtoUCS
+
+
+Please send bugs, comments, cards and letters to linuxjfs@us.ibm.com.
+
+The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe"
+at our web page http://oss.software.ibm.com/jfs/.
diff -uNr --exclude=CVS linux-2.4.9-ac10/Documentation/filesystems/jfs.txt linuxppc64_2_4/Documentation/filesystems/jfs.txt
--- linux-2.4.9-ac10/Documentation/filesystems/jfs.txt Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/Documentation/filesystems/jfs.txt Thu Sep 13 14:29:38 2001
@@ -0,0 +1,153 @@
+IBM's Journaled File System (JFS) for Linux version 1.0.4
+Team members
+Steve Best sbest@us.ibm.com
+Dave Kleikamp shaggy@us.ibm.com
+Barry Arndt barndt@us.ibm.com
+
+
+Release August 31, 2001 (version 1.0.4)
+
+This is our forty-second release of IBM's Enterprise JFS technology port to Linux.
+Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001,
+Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001.
+
+The changelog.jfs file contains detailed information of changes done in each source
+code drop.
+
+JFS has a source tree that can be built on 2.2.14 - 2.2.19 and 2.4.0 - 2.4.9
+kernel.org source trees.
+
+There is a anonymous cvs access available for the JFS tree. The steps below are
+what is needed to pull the JFS cvs tree from the oss.software.ibm.com server.
+
+id anoncvs
+password anoncvs
+
+To checkout 2.2.x series of the JFS files do the following:
+CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs
+cvs checkout linux-2.2.12
+
+To checkout 2.4.x series of the JFS files do the following:
+CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs
+cvs checkout linux24
+
+To checkout the JFS utilities do the following:
+CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs
+cvs checkout jfsutils
+
+The jfs-2.4-1.0.4-patch.tar.gz file contains a readme and patch files for different
+levels of the 2.4 kernel. Please see the README in the jfs-2.4-1.0.4-patch.tar.gz
+file for help on applying the two patch files.
+
+Similarly jfs-2.2-1.0.4-patch.tar.gz contains a readme and patch files for
+different levels of the 2.2 kernel.
+
+The following files in the kernel source tree have been changed so JFS can be built.
+The jfs-2.4-1.0.4.tar.gz source tar ball now contains each of the files below with
+the extension of the kernel level it is associated with. As an example, there are now
+three Config.in files named Config.in-2.4.0, Config.in-2.4.5, and Config.in-2.4.7.
+
+Similarly, the jfs-2.2-1.0.4.tar.gz source tar ball contains the files
+Config.in-2.2.14, Config.in-2.2.16, and Config.in-2.2.18.
+
+If you use the tar ball to build JFS you must rename each of the kernel files to the
+file names listed below. The standard kernel from www.kernel.org is the source of the
+kernel files that are included in the jfs tar files.
+
+In sub dir fs Config.in, Makefile, filesystem.c
+In sub dir fs/nls Config.in
+In sub dir arch/i386 defconfig
+In sub dir Documentation Configure.help
+In sub dir Documentation/filesystems 00-INDEX
+In sub dir include/linux fs.h
+In sub dir linux MAINTAINERS
+In sub dir linux/kernel/ksyms.c
+
+Please backup the above files before the JFS patch file is added to the kernel source
+tree. There are three new header files in the sub dir include/linux named jfs_fs.h,
+jfs_fs_i.h,and jfs_fs_sb.h. All other JFS files are located in the include/linux/jfs
+or fs/jfs sub dirs.
+
+Our development team has used the Linux kernel levels 2.2.14-2.2.19 and
+2.4.0 - 2.4.9 kernels with gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
+for our port so far. A goal of the JFS team is to have JFS run on all architectures
+that Linux supports, there is no architecture specific code in JFS. JFS has been run
+on the following architectures (x86, PowerPC, Alpha, s/390, ARM) so far.
+
+To make JFS build, during the "make config" step of building the kernel answer y to
+the Prompt for development and/or incomplete code/drivers in the Code maturity level
+options section. In the Filesystems section use the m for the answer to
+JFS filesystem support (experimental) (CONFIG_JFS_FS) [Y/m/n?]
+
+Note: If you are use JFS as module on the 2.2.x series of the kernel you must rebuild
+the kernel and run that rebuilt kernel for JFS to run. The reason for this change is
+that JFS needs to export symbols.
+
+Build in /usr/src/linux with the command:
+
+
+make modules
+make modules_install
+
+If you rebuild jfs.o after having mounted and unmounted a partition, "modprobe -r jfs"
+will unload the old module.
+
+For the file system debugging messages are being written to /var/log/messages.
+
+There are two ways to the build the JFS utilities, the first using the jfsprogs.spec
+file and the second way is to run make and then make install in the
+/jfsutils sub dir.
+
+To use the jfsprogs.spec located in sub dir jfsutils/SPECS you need to update
+the version of JFS in the spec file, also the corresponding jfs-x.x.x-patch.tar.gz file
+must be in the SOURCES directory of your system. Now it's time to begin the build. First,
+change into the directory holding jfsprogs.spec file:
+
+cd /jfsutils/SPECS
+
+Next, start the build with a rpm -b command:
+
+rpm -ba jfsprogs.spec
+
+The a following the -b option directs RPM to perform all phases of the build process.
+
+
+The second way to build the utilities for JFS (mkfs, xpeek, logredo, xchkdmp, fsck, logdump, xchklog).
+
+Build in /jfsutils with the command:
+
+make
+make install
+
+One of results of this build is a program called mkfs.jfs.
+To format a JFS partition use the following command.
+
+ mkfs -t jfs device-name
+
+will result in the specified device being formatted.
+
+
+
+JFS TODO list:
+
+Plans for our near term development items
+
+ - Fix for 2.2.* SMP kernel hangs
+ - get defrag capabilities operational in the FS
+ - get extendfs capabilities operational in the FS
+ - test EXTENDFS utility, for growing JFS partitions
+ - test defrag utility, calls file system to defrag the file system.
+ - add support for block sizes (512,1024,2048)
+ - add support for logfile on dedicated partition
+
+
+Longer term work items
+
+ - get access control list functionality operational
+ - get extended attributes functionality operational
+ - add quota support
+
+Please send bugs, comments, cards and letters to linuxjfs@us.ibm.com.
+
+The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe"
+at our web page http://oss.software.ibm.com/jfs/.
diff -uNr --exclude=CVS linux-2.4.9-ac10/MAINTAINERS linuxppc64_2_4/MAINTAINERS
--- linux-2.4.9-ac10/MAINTAINERS Mon Sep 10 11:58:10 2001
+++ linuxppc64_2_4/MAINTAINERS Thu Sep 13 14:29:38 2001
@@ -794,6 +794,13 @@
W: http://sources.redhat.com/jffs2/
S: Maintained
+JFS FILESYSTEM
+P: Dave Kleikamp
+M: shaggy@austin.ibm.com
+L: jfs-discussion@oss.software.ibm.com
+W: http://oss.software.ibm.com/developerworks/opensource/jfs/
+S: Supported
+
JOYSTICK DRIVER
P: Vojtech Pavlik
M: vojtech@suse.cz
@@ -869,14 +876,10 @@
S: Maintained
LINUX FOR 64BIT POWERPC
-P: Tom Gall
-M: tom_gall@vnet.ibm.com
P: David Engebretsen
M: engebret@us.ibm.com
-P: Dwayne McConnell
-M: dwayne@austin.ibm.com
W: http://linuxppc64.org
-L: linuxppc64-dev@lists.linuxppc.porg
+L: linuxppc64-dev@lists.linuxppc.org
S: Supported
LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
diff -uNr --exclude=CVS linux-2.4.9-ac10/Makefile linuxppc64_2_4/Makefile
--- linux-2.4.9-ac10/Makefile Mon Sep 10 11:58:10 2001
+++ linuxppc64_2_4/Makefile Mon Sep 10 10:53:31 2001
@@ -10,11 +10,13 @@
# SUBARCH tells the usermode build what the underlying arch is. That is set
# first, and if a usermode build is happening, the "ARCH=um" on the command
# line overrides the setting of ARCH below. If a native build is happening,
-# then ARCH is assigned, getting whatever value it gets normally, and
+# then ARCH is assigned, getting whatever value it gets normally, and
# SUBARCH is subsequently ignored.
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-ARCH := $(SUBARCH)
+#ARCH := $(SUBARCH)
+
+ARCH := ppc64
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
@@ -27,7 +29,7 @@
HOSTCC = gcc
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
-CROSS_COMPILE =
+CROSS_COMPILE = /usr/local/ppc64-current3.0/bin/powerpc64-linux-
#
# Include the make variables (CC, etc...)
@@ -97,7 +99,7 @@
CPPFLAGS := -D__KERNEL__ -I$(HPATH)
CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
- -fomit-frame-pointer -fno-strict-aliasing -fno-common
+ -fomit-frame-pointer -fno-strict-aliasing -fno-common
AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
#
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/i386/defconfig linuxppc64_2_4/arch/i386/defconfig
--- linux-2.4.9-ac10/arch/i386/defconfig Thu Sep 6 14:04:16 2001
+++ linuxppc64_2_4/arch/i386/defconfig Thu Sep 13 14:29:38 2001
@@ -598,6 +598,7 @@
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
+# CONFIG_JFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/Makefile linuxppc64_2_4/arch/ppc64/Makefile
--- linux-2.4.9-ac10/arch/ppc64/Makefile Thu Sep 6 14:05:09 2001
+++ linuxppc64_2_4/arch/ppc64/Makefile Fri Sep 14 10:19:30 2001
@@ -19,13 +19,19 @@
CHECKS = checks
endif
+# Re: -DPPC64_32B_ADDR_SPACE in CPPLAGS/CFLAGS below.
+# For 64-bit apps, temporarily reduce the size of the address space
+# available to user application. This allow us to use strace without
+# having to compile a strace64 program. This shouldn't affect anyone
+# other than Steve Munroe, Peter Bergner. I will back this hack out
+# later... -Peter
+
ASFLAGS =
LINKFLAGS = -T arch/ppc64/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
-CPPFLAGS := $(CPPFLAGS) -D__powerpc__ -include $(TOPDIR)/arch/ppc64/mymacros.h
-CFLAGS := $(CFLAGS) -D__linux__ -D__powerpc__ -fsigned-char -Wa,-Saix \
+CPPFLAGS := $(CPPFLAGS) -D__powerpc__ -DPPC64_32B_ADDR_SPACE
+CFLAGS := $(CFLAGS) -D__linux__ -D__powerpc__ -fsigned-char \
-msoft-float -pipe -Wno-uninitialized $(PRINTK) \
- -include $(TOPDIR)/arch/ppc64/mymacros.h -mminimal-toc \
- -fno-builtin
+ -mminimal-toc -fno-builtin -DPPC64_32B_ADDR_SPACE
CPP = $(CC) -E $(CFLAGS)
@@ -67,15 +73,9 @@
@$(MAKEBOOT) $@
endif
-.PHONY: clean_config
-clean_config:
+%_config: arch/ppc64/configs/%_defconfig
rm -f .config arch/ppc64/defconfig
-
-chrp_config: clean_config
- cp -f arch/ppc64/configs/chrp_defconfig arch/ppc64/defconfig
-
-common_config: clean_config
- cp -f arch/ppc64/configs/common_defconfig arch/ppc64/defconfig
+ cp -f arch/ppc64/configs/$(@:config=defconfig) arch/ppc64/defconfig
archclean:
rm -f arch/ppc64/kernel/{ppc_defs.h,checks,mk_defs.s,mk_defs_out.c,mk_defs_tpl}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/boot/Makefile linuxppc64_2_4/arch/ppc64/boot/Makefile
--- linux-2.4.9-ac10/arch/ppc64/boot/Makefile Thu Sep 6 14:05:09 2001
+++ linuxppc64_2_4/arch/ppc64/boot/Makefile Thu Sep 13 14:13:35 2001
@@ -29,7 +29,7 @@
$(BOOTCC) $(BOOTAFLAGS) -traditional -c -o $*.o $<
CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS
-LD_ARGS = -Ttext 0x00400000
+LD_ARGS = -Ttext 0x00400000 -e _start
OBJS = crt0.o start.o main.o zlib.o image.o imagesize.o
#LIBS = $(TOPDIR)/lib/lib.a
@@ -84,7 +84,7 @@
imagesize.c: vmlinux.gz
clean:
- rm -f piggyback note addnote $(OBJS) zImage vmlinux.gz no_initrd.o
+ rm -f piggyback note addnote $(OBJS) zImage zImage.initrd vmlinux.gz no_initrd.o imagesize.c
fastdep:
$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/boot/crt0.S linuxppc64_2_4/arch/ppc64/boot/crt0.S
--- linux-2.4.9-ac10/arch/ppc64/boot/crt0.S Thu Sep 6 14:05:09 2001
+++ linuxppc64_2_4/arch/ppc64/boot/crt0.S Thu Sep 13 14:13:35 2001
@@ -22,28 +22,28 @@
sync
isync
- ## Clear out the BSS as per ANSI C requirements
+ ## Clear out the BSS as per ANSI C requirements
- lis 7,_end@ha
- addi 7,7,_end@l # r7 = &_end
- lis 8,__bss_start@ha #
- addi 8,8,__bss_start@l # r8 = &_bss_start
+ lis 7,_end@ha
+ addi 7,7,_end@l # r7 = &_end
+ lis 8,__bss_start@ha #
+ addi 8,8,__bss_start@l # r8 = &_bss_start
- ## Determine how large an area, in number of words, to clear
-
- subf 7,8,7 # r7 = &_end - &_bss_start + 1
- addi 7,7,3 # r7 += 3
- srwi. 7,7,2 # r7 = size in words.
- beq 3f # If the size is zero, do not bother
- addi 8,8,-4 # r8 -= 4
- mtctr 7 # SPRN_CTR = number of words to clear
- li 0,0 # r0 = 0
-2: stwu 0,4(8) # Clear out a word
- bdnz 2b # If we are not done yet, keep clearing
+ ## Determine how large an area, in number of words, to clear
+
+ subf 7,8,7 # r7 = &_end - &_bss_start + 1
+ addi 7,7,3 # r7 += 3
+ srwi. 7,7,2 # r7 = size in words.
+ beq 3f # If the size is zero, do not bother
+ addi 8,8,-4 # r8 -= 4
+ mtctr 7 # SPRN_CTR = number of words to clear
+ li 0,0 # r0 = 0
+2: stwu 0,4(8) # Clear out a word
+ bdnz 2b # If we are not done yet, keep clearing
3:
- b start
+ b start
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/boot/main.c linuxppc64_2_4/arch/ppc64/boot/main.c
--- linux-2.4.9-ac10/arch/ppc64/boot/main.c Thu Sep 6 14:05:09 2001
+++ linuxppc64_2_4/arch/ppc64/boot/main.c Thu Sep 13 14:13:35 2001
@@ -10,12 +10,11 @@
*/
#define __KERNEL__
#include "zlib.h"
-#include
#include
#include
+#include
#include
-#define _ALIGN(addr,size) (((addr)+(size)-1)&(~((size)-1)))
extern void *finddevice(const char *);
extern int getprop(void *, const char *, void *, int);
@@ -25,16 +24,15 @@
void *claim(unsigned int, unsigned int, unsigned int);
void flush_cache(void *, int);
void pause(void);
+static struct bi_record *make_bi_recs(unsigned long);
#define RAM_START 0x00000000
#define RAM_END (64<<20)
#define BOOT_START ((unsigned long)_start)
-#define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF)
-
-#define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF)
+#define BOOT_END ((unsigned long)_end)
-// Value picked to match that used by yaboot
+/* Value picked to match that used by yaboot */
#define PROG_START 0x01400000
char *avail_ram;
@@ -42,6 +40,8 @@
char *avail_high;
unsigned int heap_use;
unsigned int heap_max;
+unsigned long initrd_start = 0;
+unsigned long initrd_size = 0;
extern char _end[];
extern char image_data[];
@@ -54,32 +54,37 @@
static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
+typedef void (*kernel_entry_t)( unsigned long,
+ unsigned long,
+ void *,
+ struct bi_record *);
+
void
-chrpboot(int a1, int a2, void *prom)
+chrpboot(unsigned long a1, unsigned long a2, void *prom)
{
- unsigned sa, len;
- void *dst, *claim_addr;
+ unsigned len;
+ void *dst = (void *)-1;
+ unsigned long claim_addr;
unsigned char *im;
- unsigned initrd_start, initrd_size;
extern char _start;
+ struct bi_record *bi_recs;
+ kernel_entry_t kernel_entry;
printf("chrpboot starting: loaded at 0x%x\n\r", (unsigned)&_start);
- printf(" initrd_len = 0x%x\n\r", (unsigned)initrd_len);
if (initrd_len) {
initrd_size = initrd_len;
initrd_start = (RAM_END - initrd_size) & ~0xFFF;
- a1 = initrd_start;
- a2 = initrd_size;
+ a1 = a2 = 0;
claim(initrd_start, RAM_END - initrd_start, 0);
- printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r",
- initrd_start, (unsigned)initrd_data, initrd_size);
+ printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
+ initrd_start, (unsigned long)initrd_data, initrd_size);
memcpy((void *)initrd_start, (void *)initrd_data, initrd_size);
}
im = image_data;
len = image_len;
- uncompressed_size = _ALIGN(uncompressed_size, (1<<12)); /* page align it */
+ uncompressed_size = PAGE_ALIGN(uncompressed_size);
for(claim_addr = PROG_START;
claim_addr <= PROG_START * 8;
@@ -108,48 +113,72 @@
}
flush_cache(dst, len);
- make_bi_recs((unsigned long)dst + len);
- sa = (unsigned long)dst;
- printf("start address = 0x%x\n\r", (unsigned) sa);
+ bi_recs = make_bi_recs((unsigned long)dst + len);
+
+ kernel_entry = (kernel_entry_t)dst;
+ printf( "kernel:\n\r"
+ " entry addr = 0x%lx\n\r"
+ " a1 = 0x%lx,\n\r"
+ " a2 = 0x%lx,\n\r"
+ " prom = 0x%lx,\n\r"
+ " bi_recs = 0x%lx,\n\r",
+ (unsigned long)kernel_entry, a1, a2,
+ (unsigned long)prom, (unsigned long)bi_recs);
- (*(void (*)(int, int, void *))sa)(a1, a2, prom);
+ kernel_entry( a1, a2, prom, bi_recs );
printf("returned?\n\r");
pause();
}
-void make_bi_recs(unsigned long addr)
+static struct bi_record *
+make_bi_recs(unsigned long addr)
{
+ struct bi_record *bi_recs;
struct bi_record *rec;
-
- rec = (struct bi_record *)_ALIGN(addr + (1<<20) -1, (1<<20));
+ bi_recs = rec = bi_rec_init(addr);
+
+ rec = bi_rec_alloc(rec, 1);
rec->tag = BI_FIRST;
- rec->size = sizeof(struct bi_record);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
+ /* rec->data[0] = ...; # Written below before return */
+
+ rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1);
rec->tag = BI_BOOTLOADER_ID;
sprintf( (char *)rec->data, "chrpboot");
- rec->size = sizeof(struct bi_record) + strlen("chrpboot") + 1;
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
+
+ rec = bi_rec_alloc(rec, 2);
rec->tag = BI_MACHTYPE;
- rec->data[0] = _MACH_chrp;
+ rec->data[0] = _MACH_pSeries;
rec->data[1] = 1;
- rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ if ( initrd_size > 0 ) {
+ rec = bi_rec_alloc(rec, 2);
+ rec->tag = BI_INITRD;
+ rec->data[0] = initrd_start;
+ rec->data[1] = initrd_size;
+ }
+
#if 0
- rec->tag = BI_SYSMAP;
- rec->data[0] = (unsigned long)sysmap_data;
- rec->data[1] = sysmap_len;
- rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
+ if ( sysmap_len > 0 ) {
+ rec = bi_rec_alloc(rec, 2);
+ rec->tag = BI_SYSMAP;
+ rec->data[0] = (unsigned long)sysmap_data;
+ rec->data[1] = sysmap_len;
+ }
#endif
+
+ rec = bi_rec_alloc(rec, 0);
rec->tag = BI_LAST;
- rec->size = sizeof(struct bi_record);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+ /* Save the _end_ address of the bi_rec's in the first bi_rec
+ * data field for easy access by the kernel.
+ */
+ bi_recs->data[0] = (bi_rec_field)rec + rec->size;
+
+ return bi_recs;
}
struct memchunk {
@@ -212,47 +241,48 @@
void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
{
- z_stream s;
- int r, i, flags;
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ printf("bad gzipped data\n\r");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ printf("gunzip: ran out of data in header\n\r");
+ exit();
+ }
- /* skip header */
- i = 10;
- flags = src[3];
- if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
- printf("bad gzipped data\n\r");
- exit();
- }
- if ((flags & EXTRA_FIELD) != 0)
- i = 12 + src[10] + (src[11] << 8);
- if ((flags & ORIG_NAME) != 0)
- while (src[i++] != 0)
- ;
- if ((flags & COMMENT) != 0)
- while (src[i++] != 0)
- ;
- if ((flags & HEAD_CRC) != 0)
- i += 2;
- if (i >= *lenp) {
- printf("gunzip: ran out of data in header\n\r");
- exit();
- }
-
- s.zalloc = zalloc;
- s.zfree = zfree;
- r = inflateInit2(&s, -MAX_WBITS);
- if (r != Z_OK) {
- printf("inflateInit2 returned %d\n\r", r);
- exit();
- }
- s.next_in = src + i;
- s.avail_in = *lenp - i;
- s.next_out = dst;
- s.avail_out = dstlen;
- r = inflate(&s, Z_FINISH);
- if (r != Z_OK && r != Z_STREAM_END) {
- printf("inflate returned %d msg: %s\n\r", r, s.msg);
- exit();
- }
- *lenp = s.next_out - (unsigned char *) dst;
- inflateEnd(&s);
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ printf("inflateInit2 returned %d\n\r", r);
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ printf("inflate returned %d msg: %s\n\r", r, s.msg);
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
}
+
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/boot/start.c linuxppc64_2_4/arch/ppc64/boot/start.c
--- linux-2.4.9-ac10/arch/ppc64/boot/start.c Thu Sep 6 14:05:09 2001
+++ linuxppc64_2_4/arch/ppc64/boot/start.c Thu Sep 13 14:13:35 2001
@@ -30,200 +30,200 @@
void
start(int a1, int a2, void *promptr)
{
- prom = (int (*)(void *)) promptr;
- chosen_handle = finddevice("/chosen");
- if (chosen_handle == (void *) -1)
- exit();
- if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
- exit();
- stderr = stdout;
- if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
+ prom = (int (*)(void *)) promptr;
+ chosen_handle = finddevice("/chosen");
+ if (chosen_handle == (void *) -1)
+ exit();
+ if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
+ exit();
+ stderr = stdout;
+ if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
exit();
- chrpboot(a1, a2, promptr);
- for (;;)
- exit();
+ chrpboot(a1, a2, promptr);
+ for (;;)
+ exit();
}
int
write(void *handle, void *ptr, int nb)
{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- void *ihandle;
- void *addr;
- int len;
- int actual;
- } args;
-
- args.service = "write";
- args.nargs = 3;
- args.nret = 1;
- args.ihandle = handle;
- args.addr = ptr;
- args.len = nb;
- args.actual = -1;
- (*prom)(&args);
- return args.actual;
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *ihandle;
+ void *addr;
+ int len;
+ int actual;
+ } args;
+
+ args.service = "write";
+ args.nargs = 3;
+ args.nret = 1;
+ args.ihandle = handle;
+ args.addr = ptr;
+ args.len = nb;
+ args.actual = -1;
+ (*prom)(&args);
+ return args.actual;
}
int
read(void *handle, void *ptr, int nb)
{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- void *ihandle;
- void *addr;
- int len;
- int actual;
- } args;
-
- args.service = "read";
- args.nargs = 3;
- args.nret = 1;
- args.ihandle = handle;
- args.addr = ptr;
- args.len = nb;
- args.actual = -1;
- (*prom)(&args);
- return args.actual;
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *ihandle;
+ void *addr;
+ int len;
+ int actual;
+ } args;
+
+ args.service = "read";
+ args.nargs = 3;
+ args.nret = 1;
+ args.ihandle = handle;
+ args.addr = ptr;
+ args.len = nb;
+ args.actual = -1;
+ (*prom)(&args);
+ return args.actual;
}
void
exit()
{
- struct prom_args {
- char *service;
- } args;
+ struct prom_args {
+ char *service;
+ } args;
- for (;;) {
- args.service = "exit";
- (*prom)(&args);
- }
+ for (;;) {
+ args.service = "exit";
+ (*prom)(&args);
+ }
}
void
pause(void)
{
- struct prom_args {
- char *service;
- } args;
+ struct prom_args {
+ char *service;
+ } args;
- args.service = "enter";
- (*prom)(&args);
+ args.service = "enter";
+ (*prom)(&args);
}
void *
finddevice(const char *name)
{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- const char *devspec;
- void *phandle;
- } args;
-
- args.service = "finddevice";
- args.nargs = 1;
- args.nret = 1;
- args.devspec = name;
- args.phandle = (void *) -1;
- (*prom)(&args);
- return args.phandle;
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ const char *devspec;
+ void *phandle;
+ } args;
+
+ args.service = "finddevice";
+ args.nargs = 1;
+ args.nret = 1;
+ args.devspec = name;
+ args.phandle = (void *) -1;
+ (*prom)(&args);
+ return args.phandle;
}
void *
-claim(unsigned int virt, unsigned int size, unsigned int align)
+claim(unsigned long virt, unsigned long size, unsigned long align)
{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- unsigned int virt;
- unsigned int size;
- unsigned int align;
- void *ret;
- } args;
-
- args.service = "claim";
- args.nargs = 3;
- args.nret = 1;
- args.virt = virt;
- args.size = size;
- args.align = align;
- (*prom)(&args);
- return args.ret;
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ unsigned int virt;
+ unsigned int size;
+ unsigned int align;
+ void *ret;
+ } args;
+
+ args.service = "claim";
+ args.nargs = 3;
+ args.nret = 1;
+ args.virt = virt;
+ args.size = size;
+ args.align = align;
+ (*prom)(&args);
+ return args.ret;
}
int
getprop(void *phandle, const char *name, void *buf, int buflen)
{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- void *phandle;
- const char *name;
- void *buf;
- int buflen;
- int size;
- } args;
-
- args.service = "getprop";
- args.nargs = 4;
- args.nret = 1;
- args.phandle = phandle;
- args.name = name;
- args.buf = buf;
- args.buflen = buflen;
- args.size = -1;
- (*prom)(&args);
- return args.size;
+ struct prom_args {
+ char *service;
+ int nargs;
+ int nret;
+ void *phandle;
+ const char *name;
+ void *buf;
+ int buflen;
+ int size;
+ } args;
+
+ args.service = "getprop";
+ args.nargs = 4;
+ args.nret = 1;
+ args.phandle = phandle;
+ args.name = name;
+ args.buf = buf;
+ args.buflen = buflen;
+ args.size = -1;
+ (*prom)(&args);
+ return args.size;
}
int
putc(int c, void *f)
{
- char ch = c;
+ char ch = c;
- if (c == '\n')
- putc('\r', f);
- return write(f, &ch, 1) == 1? c: -1;
+ if (c == '\n')
+ putc('\r', f);
+ return write(f, &ch, 1) == 1? c: -1;
}
int
putchar(int c)
{
- return putc(c, stdout);
+ return putc(c, stdout);
}
int
fputs(char *str, void *f)
{
- int n = strlen(str);
+ int n = strlen(str);
- return write(f, str, n) == n? 0: -1;
+ return write(f, str, n) == n? 0: -1;
}
int
readchar(void)
{
- char ch;
+ char ch;
- for (;;) {
- switch (read(stdin, &ch, 1)) {
- case 1:
- return ch;
- case -1:
- printk("read(stdin) returned -1\r\n");
- return -1;
+ for (;;) {
+ switch (read(stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ printk("read(stdin) returned -1\r\n");
+ return -1;
+ }
}
- }
}
static char line[256];
@@ -233,53 +233,53 @@
int
getchar(void)
{
- int c;
+ int c;
- if (lineleft == 0) {
- lineptr = line;
- for (;;) {
- c = readchar();
- if (c == -1 || c == 4)
- break;
- if (c == '\r' || c == '\n') {
- *lineptr++ = '\n';
- putchar('\n');
- break;
- }
- switch (c) {
- case 0177:
- case '\b':
- if (lineptr > line) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- --lineptr;
- }
- break;
- case 'U' & 0x1F:
- while (lineptr > line) {
- putchar('\b');
- putchar(' ');
- putchar('\b');
- --lineptr;
- }
- break;
- default:
- if (lineptr >= &line[sizeof(line) - 1])
- putchar('\a');
- else {
- putchar(c);
- *lineptr++ = c;
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ putchar('\a');
+ else {
+ putchar(c);
+ *lineptr++ = c;
+ }
+ }
}
- }
+ lineleft = lineptr - line;
+ lineptr = line;
}
- lineleft = lineptr - line;
- lineptr = line;
- }
- if (lineleft == 0)
- return -1;
- --lineleft;
- return *lineptr++;
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/boot/zImage.lds linuxppc64_2_4/arch/ppc64/boot/zImage.lds
--- linux-2.4.9-ac10/arch/ppc64/boot/zImage.lds Thu Sep 6 14:05:09 2001
+++ linuxppc64_2_4/arch/ppc64/boot/zImage.lds Tue Sep 11 08:57:14 2001
@@ -33,6 +33,7 @@
*(.fixup)
*(.got1)
}
+ . = ALIGN(4096);
_etext = .;
PROVIDE (etext = .);
.rodata :
@@ -45,7 +46,7 @@
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
/* Read-write section, merged into data segment: */
- . = (. + 0x0FFF) & 0xFFFFF000;
+ . = ALIGN(4096);
.data :
{
*(.data)
@@ -56,11 +57,13 @@
*(.dynamic)
CONSTRUCTORS
}
+ . = ALIGN(4096);
_edata = .;
PROVIDE (edata = .);
.fixup : { *(.fixup) }
+ . = ALIGN(4096);
__bss_start = .;
.bss :
{
@@ -69,6 +72,7 @@
*(.bss)
*(COMMON)
}
+ . = ALIGN(4096);
_end = . ;
PROVIDE (end = .);
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/configs/iSeries_nodevfs_ideemul_defconfig linuxppc64_2_4/arch/ppc64/configs/iSeries_nodevfs_ideemul_defconfig
--- linux-2.4.9-ac10/arch/ppc64/configs/iSeries_nodevfs_ideemul_defconfig Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/configs/iSeries_nodevfs_ideemul_defconfig Wed Sep 5 14:51:30 2001
@@ -0,0 +1,573 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC64=y
+CONFIG_ALL_PPC=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_PPC_PSERIES is not set
+CONFIG_PPC_ISERIES=y
+CONFIG_SMP=y
+CONFIG_MSCHUNKS=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# General setup
+#
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_EISA is not set
+CONFIG_PCI=y
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_ELF32=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PNPBIOS is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_VIODASD=y
+CONFIG_VIODASD_IDE=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=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=64000
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+# 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=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+CONFIG_RTNETLINK=y
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_RTNETLINK=y
+CONFIG_NETLINK=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_LARGE_TABLES=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=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_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
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_OAKNET is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNGEM 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_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+CONFIG_VETH=y
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+CONFIG_CD_NO_IDESCSI=y
+# CONFIG_AZTCD is not set
+# CONFIG_GSCD is not set
+# CONFIG_SBPCD is not set
+# CONFIG_MCD is not set
+# CONFIG_MCDX is not set
+# CONFIG_OPTCD is not set
+# CONFIG_CM206 is not set
+# CONFIG_SJCD is not set
+# CONFIG_ISP16_CDI is not set
+# CONFIG_CDU31A is not set
+# CONFIG_CDU535 is not set
+CONFIG_VIOCD=y
+# CONFIG_VIOCD_AZTECH is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=1024
+CONFIG_VIOCONS=y
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+CONFIG_VIOTAPE=y
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# File systems
+#
+CONFIG_QUOTA=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO 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_CMS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_FREEVXFS_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=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+CONFIG_ROMFS_FS=y
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS 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_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_ROOT_NFS is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SMB_FS=y
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_NCP_FS=y
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_SMB_NLS=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 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
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_HID is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_WACOM is not set
+# 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_HPUSBSCSI is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_ID75 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+# CONFIG_PPCDBG is not set
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/configs/pSeries_defconfig linuxppc64_2_4/arch/ppc64/configs/pSeries_defconfig
--- linux-2.4.9-ac10/arch/ppc64/configs/pSeries_defconfig Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/configs/pSeries_defconfig Fri Sep 14 10:19:31 2001
@@ -26,6 +26,9 @@
# Loadable module support
#
CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
#
# General setup
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/defconfig linuxppc64_2_4/arch/ppc64/defconfig
--- linux-2.4.9-ac10/arch/ppc64/defconfig Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/defconfig Fri Aug 31 15:48:52 2001
@@ -26,6 +26,9 @@
# Loadable module support
#
CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
#
# General setup
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/ItLpQueue.c linuxppc64_2_4/arch/ppc64/kernel/ItLpQueue.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/ItLpQueue.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/ItLpQueue.c Fri Sep 14 10:03:28 2001
@@ -10,14 +10,42 @@
#include
#include
+#include
#include
#include
#include
#include
#include
+static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
+{
+ int t;
+ u32 * inUseP = &(lpQueue->xInUseWord);
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%2 \n\
+ cmpi 0,%0,0 \n\
+ li %0,0 \n\
+ bne- 2f \n\
+ addi %0,%0,1 \n\
+ stwcx. %0,0,%2 \n\
+ bne- 1b \n\
+2: eieio"
+ : "=&r" (t), "=m" (lpQueue->xInUseWord)
+ : "r" (inUseP), "m" (lpQueue->xInUseWord)
+ : "cc");
+
+ return t;
+}
+
+static __inline__ void clear_inUse( struct ItLpQueue * lpQueue )
+{
+ lpQueue->xInUseWord = 0;
+}
+
/* Array of LpEvent handler functions */
extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
+unsigned long ItLpQueueInProcess = 0;
struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue )
{
@@ -72,11 +100,24 @@
event->xFlags.xValid = 0;
}
+unsigned lpQueue_proc_count[32] = {};
+
unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs )
{
unsigned numIntsProcessed = 0;
struct HvLpEvent * nextLpEvent;
+
+ /* If we have recursed, just return */
+ if ( !set_inUse( lpQueue ) )
+ return 0;
+ if (ItLpQueueInProcess == 0)
+ ItLpQueueInProcess = 1;
+ else
+ BUG();
+
+ ++lpQueue_proc_count[current->processor];
+
for (;;) {
nextLpEvent = ItLpQueue_getNextLpEvent( lpQueue );
if ( nextLpEvent ) {
@@ -119,5 +160,10 @@
else /* If nothing left then we are done */
break;
}
+
+ ItLpQueueInProcess = 0;
+ mb();
+ clear_inUse( lpQueue );
+
return numIntsProcessed;
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/Makefile linuxppc64_2_4/arch/ppc64/kernel/Makefile
--- linux-2.4.9-ac10/arch/ppc64/kernel/Makefile Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/Makefile Mon Sep 10 13:54:26 2001
@@ -25,15 +25,16 @@
LparData.o udbg.o binfmt_elf32.o sys_ppc32.o sys32.o \
ioctl32.o ptrace32.o signal32.o open_pic.o xics.o \
pmc.o mf_proc.o proc_pmc.o proc_pcifr.o iSeries_setup.o \
- ItLpQueue.o hvCall.o mf.o viopath.o HvLpEvent.o \
+ ItLpQueue.o hvCall.o mf.o HvLpEvent.o \
iSeries_proc.o HvCall.o flight_recorder.o HvLpConfig.o
-obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o
ifeq ($(CONFIG_PPC_ISERIES),y)
-obj-$(CONFIG_PCI) += iSeries_dma.o iSeries_rtc.o
-else
-obj-$(CONFIG_PCI) += pci_dma.o
+obj-$(CONFIG_PCI) += iSeries_rtc.o iSeries_pci.o iSeries_IoMmTable.o iSeries_irq.o XmPciLpEvent.o
+endif
+ifeq ($(CONFIG_PPC_PSERIES),y)
+obj-$(CONFIG_PCI) += pSeries_pci.o
endif
obj-$(CONFIG_KGDB) += ppc-stub.o
@@ -47,7 +48,7 @@
ifeq ($(CONFIG_ALL_PPC),y)
obj-y += prom.o lmb.o rtas.o rtas-eventscan.o rtas-proc.o chrp_setup.o \
- chrp_time.o pSeries_pci.o i8259.o
+ chrp_time.o i8259.o
endif
include $(TOPDIR)/Rules.make
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/XmPciLpEvent.c linuxppc64_2_4/arch/ppc64/kernel/XmPciLpEvent.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/XmPciLpEvent.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/XmPciLpEvent.c Mon Aug 27 17:30:33 2001
@@ -0,0 +1,150 @@
+/*
+ * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001.
+ *
+ * This module handles PCI interrupt events sent by the AS400 Hypervisor.
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+enum XmPciLpEvent_Subtype {
+ XmPciLpEvent_BusCreated = 0, // PHB has been created
+ XmPciLpEvent_BusFailed = 1, // PHB has failed
+ XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
+ XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
+ XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
+ XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
+};
+
+struct XmPciLpEvent_BusInterrupt {
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+};
+
+struct XmPciLpEvent_NodeInterrupt {
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+ HvAgentId deviceId;
+};
+
+struct XmPciLpEvent {
+ struct HvLpEvent hvLpEvent;
+
+ union {
+ u64 alignData; // Align on an 8-byte boundary
+
+ struct {
+ u32 fisr;
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+ HvAgentId deviceId;
+ } slotInterrupt;
+
+ struct XmPciLpEvent_BusInterrupt busFailed;
+ struct XmPciLpEvent_BusInterrupt busRecovered;
+ struct XmPciLpEvent_BusInterrupt busCreated;
+
+ struct XmPciLpEvent_NodeInterrupt nodeFailed;
+ struct XmPciLpEvent_NodeInterrupt nodeRecovered;
+
+ } eventData;
+
+};
+
+static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm);
+
+static void XmPciLpEvent_handler( struct HvLpEvent* eventParm, struct pt_regs* regsParm) {
+ if (eventParm && eventParm->xType == HvLpEvent_Type_PciIo) {
+ switch( eventParm->xFlags.xFunction ) {
+ case HvLpEvent_Function_Int:
+ intReceived( (struct XmPciLpEvent*)eventParm, regsParm );
+ break;
+ case HvLpEvent_Function_Ack:
+ printk(KERN_ERR "XmPciLpEvent.c: unexpected ack received\n");
+ break;
+ default:
+ printk(KERN_ERR "XmPciLpEvent.c: unexpected event function %d\n",
+ (int)eventParm->xFlags.xFunction);
+ break;
+ };
+ }
+ else {
+ if (event) {
+ printk(KERN_ERR "XmPciLpEvent.c: unrecognized event type 0x%x\n",
+ (int)eventParm->xType);
+ }
+ else {
+ printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
+ }
+ }
+}
+
+static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm) {
+ int irq;
+
+ switch (eventParm->hvLpEvent.xSubtype) {
+ case XmPciLpEvent_SlotInterrupt:
+ irq = eventParm->hvLpEvent.xCorrelationToken;
+ /* Dispatch the interrupt handlers for this irq */
+ ppc_irq_dispatch_handler(regsParm, irq);
+ HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
+ eventParm->eventData.slotInterrupt.subBusNumber,
+ eventParm->eventData.slotInterrupt.deviceId);
+ break;
+ /* Ignore error recovery events for now */
+ case XmPciLpEvent_BusCreated:
+ printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", eventParm->eventData.busCreated.busNumber);
+ break;
+ case XmPciLpEvent_BusFailed:
+ printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", eventParm->eventData.busFailed.busNumber);
+ break;
+ case XmPciLpEvent_BusRecovered:
+ printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", eventParm->eventData.busRecovered.busNumber);
+ break;
+ case XmPciLpEvent_NodeFailed:
+ printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", eventParm->eventData.nodeFailed.busNumber, eventParm->eventData.nodeFailed.subBusNumber, eventParm->eventData.nodeFailed.deviceId);
+ break;
+ case XmPciLpEvent_NodeRecovered:
+ printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n", eventParm->eventData.nodeRecovered.busNumber, eventParm->eventData.nodeRecovered.subBusNumber, eventParm->eventData.nodeRecovered.deviceId);
+ break;
+ default:
+ printk(KERN_ERR "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
+ eventParm->hvLpEvent.xSubtype);
+ break;
+ };
+}
+
+
+/* This should be called sometime prior to buswalk (init_IRQ would be good) */
+int XmPciLpEvent_init() {
+ int xRc;
+
+ xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, &XmPciLpEvent_handler);
+ if (xRc == 0) {
+ xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+ if (xRc != 0) {
+ printk(KERN_ERR "XmPciLpEvent.c: open event path failed with rc 0x%x\n", xRc);
+ }
+ }
+ else {
+ printk(KERN_ERR "XmPciLpEvent.c: register handler failed with rc 0x%x\n", xRc);
+ }
+
+ return xRc;
+}
+
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/align.c linuxppc64_2_4/arch/ppc64/kernel/align.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/align.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/align.c Fri Sep 14 07:41:02 2001
@@ -252,11 +252,6 @@
}
flags = aligninfo[instr].flags;
-
- /* For the 4xx-family processors, the 'dar' field of the
- * pt_regs structure is overloaded and is really from the DEAR.
- */
-
addr = (unsigned char *)regs->dar;
/* Verify the address of the operand */
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/chrp_setup.c linuxppc64_2_4/arch/ppc64/kernel/chrp_setup.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/chrp_setup.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/chrp_setup.c Thu Sep 13 14:13:35 2001
@@ -83,7 +83,6 @@
char raw_mode);
extern char pckbd_unexpected_up(unsigned char keycode);
extern void pckbd_leds(unsigned char leds);
-extern int pckbd_rate(struct kbd_repeat *rep);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
extern void openpic_init_IRQ(void);
@@ -100,8 +99,6 @@
extern int probingmem;
extern unsigned long loops_per_jiffy;
-extern void *comport1;
-
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
@@ -254,10 +251,49 @@
ppc_md.progress(UTS_RELEASE, 0x7777);
}
+
+/* Early initialization. Relocation is on but do not reference unbolted pages */
+void __init pSeries_init_early(void)
+{
+#ifdef CONFIG_PPC_PSERIES /* This ifdef should go away */
+ void *comport;
+
+ htpe_init_pSeries();
+ tce_init_pSeries();
+ pSeries_pcibios_init_early();
+
+#ifdef CONFIG_VT
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x63; /* Print Screen */
+#endif
+#endif
+
+#ifdef CONFIG_SMP
+ smp_init_pSeries();
+#endif
+
+ /* Map the uart for udbg. */
+ comport = (void *)ioremap(naca->serialPortAddr, 16);
+ udbg_init_uart(comport);
+
+ ppc_md.udbg_putc = udbg_putc;
+ ppc_md.udbg_getc = udbg_getc;
+ ppc_md.udbg_getc_poll = udbg_getc_poll;
+#endif
+}
+
void __init
chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+#if 0 /* PPPBBB remove this later... -Peter */
#ifdef CONFIG_BLK_DEV_INITRD
/* take care of initrd if we have one */
if ( r6 )
@@ -266,8 +302,7 @@
initrd_end = __va(r6 + r7);
}
#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
+#endif
ppc_md.ppc_machine = _machine;
@@ -303,20 +338,6 @@
ppc_md.get_rtc_time = chrp_get_rtc_time;
ppc_md.calibrate_decr = chrp_calibrate_decr;
-#ifdef CONFIG_VT
- ppc_md.kbd_setkeycode = pckbd_setkeycode;
- ppc_md.kbd_getkeycode = pckbd_getkeycode;
- ppc_md.kbd_translate = pckbd_translate;
- ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
- ppc_md.kbd_leds = pckbd_leds;
- ppc_md.kbd_init_hw = pckbd_init_hw;
- ppc_md.kbd_rate = pckbd_rate;
-#ifdef CONFIG_MAGIC_SYSRQ
- ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
- SYSRQ_KEY = 0x63; /* Print Screen */
-#endif /* CONFIG_MAGIC_SYSRQ */
-#endif /* CONFIG_VT */
-
ppc_md.progress = chrp_progress;
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
@@ -332,6 +353,7 @@
ppc_ide_md.io_base = _IO_BASE;
#endif
+
ppc_md.progress("Linux ppc64\n", 0x0);
}
@@ -343,12 +365,12 @@
char *os;
static int max_width;
- if ( (_machine != _MACH_chrp) || !rtas.base )
- return;
-
if (hex)
udbg_printf(" %s\n", s);
+ if (!rtas.base || (_machine != _MACH_pSeries))
+ return;
+
if (max_width == 0) {
if ( (root = find_path_device("/rtas")) &&
(p = (unsigned int *)get_property(root,
@@ -385,10 +407,3 @@
while ( width-- > 0 )
call_rtas( "display-character", 1, 1, NULL, ' ' );
}
-
-void chrp_init_map_io_space(void)
-{
- /* naca->serialPortAddr is initialized earlier in prom.c */
- comport1 = (void *)ioremap(naca->serialPortAddr, PAGE_SIZE);
-}
-
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/entry.S linuxppc64_2_4/arch/ppc64/kernel/entry.S
--- linux-2.4.9-ac10/arch/ppc64/kernel/entry.S Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/entry.S Fri Sep 14 22:08:48 2001
@@ -32,6 +32,10 @@
#include
#include
+#ifdef CONFIG_PPC_ISERIES
+#define DO_SOFT_DISABLE
+#endif
+
#undef SHOW_SYSCALLS
#undef SHOW_SYSCALLS_TASK
@@ -324,19 +328,19 @@
_GLOBAL(ret_from_except)
#ifdef CONFIG_PPC_ISERIES
- ld r5,_MSR(r1)
- andi. r5,r5,MSR_EE
+ ld r5,SOFTE(r1)
+ cmpdi 0,r5,0
beq 4f
irq_recheck:
- mfmsr r5
- andi. r5,r5,MSR_EE
- bne 4f
/*
* Check for pending interrupts (iSeries)
*/
- CHECKANYINT(r4,r5)
+ CHECKANYINT(r3,r4)
beq+ 4f /* skip do_IRQ if no interrupts */
+ mfspr r5,SPRG3
+ li r3,0
+ stb r3,PACAPROCENABLED(r5) /* ensure we are disabled */
addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_IRQ
b irq_recheck /* loop back and handle more */
@@ -386,23 +390,31 @@
rldicl r0,r0,16,0 /* clear MSR_EE */
mtmsrd r0 /* Update machine state */
#ifdef CONFIG_PPC_ISERIES
- ld r0,_MSR(r1)
- andi. r3,r0,MSR_EE
+ ld r0,SOFTE(r1)
+ cmpi 0,r0,0
beq+ 1f
CHECKANYINT(r4,r3)
- bne- irq_recheck
+ beq+ 1f
+ mfmsr r0
+ ori r0,r0,MSR_EE
+ mtmsr r0
+ b irq_recheck
1:
#endif
stdcx. r0,0,r1 /* to clear the reservation */
+ mfspr r4,SPRG3 /* current task's PACA */
+#ifdef DO_SOFT_DISABLE
+ ld r0,SOFTE(r1)
+ stb r0,PACAPROCENABLED(r4)
+#endif
/* if returning to user mode, save kernel SP */
ld r0,_MSR(r1)
andi. r0,r0,MSR_PR
beq+ 1f
addi r0,r1,INT_FRAME_SIZE /* size of frame */
- mfspr r4,SPRG3 /* current task's PACA */
ld r2,PACACURRENT(r4) /* Get 'current' */
std r0,THREAD+KSP(r2) /* save kernel stack pointer */
std r1,PACAKSAVE(r4) /* save exception stack pointer */
@@ -419,9 +431,6 @@
ld r4,GPR4(r1)
ld r1,GPR1(r1)
- /* sync required to force memory operations on this processor */
- /* to complete before the current thread gives up control. */
- SYNC
rfid
#ifdef CONFIG_PPC_ISERIES
@@ -633,7 +642,7 @@
rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
andc r11,r11,r12
mtmsrd r11
- SYNC
+ isync
REST_8GPRS(2, r1) // Restore the TOC & incoming param(s)
REST_8GPRS(14, r1) // Restore the non-volatiles
@@ -643,7 +652,7 @@
mfspr r1,SPRG2
ld r6,_MSR(r1)
mtmsrd r6
- SYNC
+ isync
REST_GPR(2, r1) // Restore the TOC
REST_8GPRS(14, r1) // Restore the non-volatiles
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/head.S linuxppc64_2_4/arch/ppc64/kernel/head.S
--- linux-2.4.9-ac10/arch/ppc64/kernel/head.S Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/head.S Mon Sep 17 12:28:46 2001
@@ -35,6 +35,10 @@
#include
#include
+#ifdef CONFIG_PPC_ISERIES
+#define DO_SOFT_DISABLE
+#endif
+
/*
* We layout physical memory as follows:
* 0x0000 - 0x00ff : Secondary processor spin code
@@ -47,6 +51,17 @@
*/
/*
+ * SPRG Usage
+ *
+ * Register Definition
+ *
+ * SPRG0 reserved for hypervisor
+ * SPRG1 temp - used to save gpr
+ * SPRG2 temp - used to save gpr
+ * SPRG3 virt addr of Paca
+ */
+
+/*
* Entering into this code we make the following assumptions:
* For pSeries:
* 1. The MMU is off & open firmware is running in real mode.
@@ -135,72 +150,114 @@
* This is the start of the interrupt handlers for Pseries
* This code runs with relocation off.
*/
+#define EXCEPTION_PROLOG_PSERIES(label) \
+ mtspr SPRG2,r20; /* use SPRG2 as scratch reg */ \
+ mtspr SPRG1,r21; /* save r21 */ \
+ mfspr r20,SPRG3; /* get Paca virt addr */ \
+ clrldi r20,r20,12; /* convert virt to real addr */ \
+ ld r21,PACAEXCSP(r20); /* get exception stack ptr */ \
+ addi r21,r21,-EXC_FRAME_SIZE; /* make exception frame */ \
+ std r21,PACAEXCSP(r20); /* update exception stack ptr */ \
+ clrldi r20,r21,12; /* convert virt to real addr */ \
+ std r22,32(r20); /* Save r22 in exc. frame */ \
+ std r23,40(r20); /* Save r23 in exc. frame */ \
+ mfspr r22,SRR0; /* EA of interrupted instr */ \
+ std r22,0(r20); /* Save SRR0 in exc. frame */ \
+ mfspr r23,SRR1; /* machine state at interrupt */ \
+ std r23,8(r20); /* Save SRR1 in exc. frame */ \
+ mfspr r22,SPRG2; \
+ std r22,16(r20); /* Save r20 in exc. frame */ \
+ mfspr r23,SPRG1; \
+ std r23,24(r20); /* Save r21 in exc. frame */ \
+ mfspr r20,SPRG3; /* get Paca virt addr again */ \
+ SET_REG_TO_LABEL(r22,label); /* Get addr to branch to */ \
+ mfmsr r23; \
+ rotldi r23,r23,4; \
+ ori r23,r23,0x32B; /* Set IR, DR, RI, SF, ISF, HV*/ \
+ rotldi r23,r23,60; /* for generic handlers */ \
+ mtspr SRR0,r22; \
+ mtspr SRR1,r23; \
+ mfcr r23; /* save CR in r23 */ \
+ rfid
-#define EXCEPTION_PROLOG_PSERIES(label) \
- mtspr SPRG2,r20; /* use SPRG2 as scratch reg */ \
- mfspr r20,SPRG3; /* get Paca virt addr */ \
- clrldi r20,r20,12; /* convert virt to real addr */ \
- std r21,PACAR21(r20); /* Save GPR21 in Paca */ \
- mfspr r21,SRR0; /* EA of interrupted instr */ \
- std r21,LPPACA+LPPACASRR0(r20); /* Set SRR0 in ItLpPaca */ \
- mfspr r21,SRR1; /* machine state at interrupt */ \
- std r21,LPPACA+LPPACASRR1(r20); /* Set SRR1 in ItLpPaca */ \
- SET_REG_TO_LABEL(r21,label); /* Get addr to branch to */ \
- mtspr SRR0,r21; \
- li r20,0x5; /* Turn on 64b, 64bints */ \
- sldi r20,r20,61; \
- ori r20,r20,0x30; /* for generic handlers */ \
- mfmsr r21; /* Turn on IR & DR */ \
- or r21,r21,r20; /* for generic handlers */ \
- mtspr SRR1,r21; \
- rfid /* Jump to generic handlers */
/*
* This is the start of the interrupt handlers for i_series
* This code runs with relocation on.
*/
-
#define EXCEPTION_PROLOG_ISERIES \
- mtspr SPRG2,r20; /* use SPRG2 as scratch reg */\
- mfspr r20,SPRG3; /* get Paca */\
- std r21,PACAR21(r20) /* Save GPR21 in Paca */
-
-#define EXCEPTION_PROLOG_COMMON \
- mfspr r20,SPRG3; /* get Paca virt addr */ \
- std r22,PACAR22(r20); /* Save GPR22 in Paca */\
- mfcr r22; \
- ld r21,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */ \
- andi. r21,r21,MSR_PR; /* Set CR for later branch */ \
- beq+ 1f; \
- ld r21,PACAKSAVE(r20); /* exception stack to use */\
- b 2f; \
-1: \
- subi r21,r1,INT_FRAME_SIZE;/* alloc exc. frame */ \
-2: \
- std r22,_CCR(r21); /* save CR in stackframe */\
- ld r22,PACAR21(r20); /* Get GPR21 from Paca */\
- std r22,GPR21(r21); /* Save GPR21 in stackframe */\
- ld r22,PACAR22(r20); /* Get GPR22 from Paca */\
- std r22,GPR22(r21); /* Save GPR22 in stackframe */\
- std r23,GPR23(r21); /* Save GPR23 in stackframe */\
- mfspr r22,SPRG2; /* Get GPR20 from SPRG2 */\
- std r22,GPR20(r21); /* Save GPR20 in stackframe */\
- mflr r22; \
- std r22,_LINK(r21); \
- mfctr r22; \
- std r22,_CTR(r21); \
- mfspr r22,XER; \
- std r22,_XER(r21); \
- ld r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */\
- ld r23,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */\
- SAVE_8GPRS(0, r21); \
- SAVE_4GPRS(8, r21); \
- SAVE_2GPRS(12, r21); \
- ld r2,PACATOC(r20); \
- std r1,0(r21); \
- mr r1,r21
+ mtspr SPRG2,r20; /* use SPRG2 as scratch reg */\
+ mtspr SPRG1,r21; /* save r21 */\
+ mfspr r20,SPRG3; /* get Paca */\
+ ld r21,PACAEXCSP(r20); /* get exception stack ptr */\
+ addi r21,r21,-EXC_FRAME_SIZE; /* make exception frame */\
+ std r21,PACAEXCSP(r20); /* update exception stack ptr */\
+ std r22,32(r21); /* save r22 on exception frame */\
+ std r23,40(r21); /* Save r23 in exc. frame */\
+ ld r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */\
+ std r22,0(r21); /* save SRR0 in exc. frame */\
+ ld r23,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */\
+ std r23,8(r21); /* save SRR1 in exc. frame */\
+ mfspr r22,SPRG2; \
+ std r22,16(r21); /* Save r20 in exc. frame */\
+ mfspr r23,SPRG1; \
+ std r23,24(r21); /* Save r21 in exc. frame */\
+ mfcr r23; /* save CR in r23 */
+
+/*
+ * The common exception prolog is used for all except a few exceptions
+ * such as a segment miss on a kernel address. We have to be prepared
+ * to take another exception from the point where we first touch the
+ * kernel stack onwards.
+ *
+ * On entry r20 points to the paca and r21 points to the exception
+ * frame on entry, r23 contains the saved CR, and relocation is on.
+ */
+#define EXCEPTION_PROLOG_COMMON \
+ mfspr r22,DAR; /* Save DAR in exc. frame */ \
+ std r22,48(r21); \
+ mfspr r22,DSISR; /* Save DSISR in exc. frame */ \
+ std r22,56(r21); \
+ ld r22,8(r21); /* Get SRR1 from exc. frame */ \
+ andi. r22,r22,MSR_PR; /* Set CR for later branch */ \
+ mr r22,r1; /* Save r1 */ \
+ subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \
+ beq- 1f; \
+ ld r1,PACAKSAVE(r20); /* kernel stack to use */ \
+1: std r22,GPR1(r1); /* save r1 in stackframe */ \
+ std r22,0(r1); /* make stack chain pointer */ \
+ std r23,_CCR(r1); /* save CR in stackframe */ \
+ ld r22,16(r21); /* move r20 to stackframe */ \
+ std r22,GPR20(r1); \
+ ld r23,24(r21); /* move r21 to stackframe */ \
+ std r23,GPR21(r1); \
+ ld r22,32(r21); /* move r22 to stackframe */ \
+ std r22,GPR22(r1); \
+ ld r23,40(r21); /* move r23 to stackframe */ \
+ std r23,GPR23(r1); \
+ mflr r22; /* save LR in stackframe */ \
+ std r22,_LINK(r1); \
+ mfctr r23; /* save CTR in stackframe */ \
+ std r23,_CTR(r1); \
+ mfspr r22,XER; /* save XER in stackframe */ \
+ std r22,_XER(r1); \
+ ld r23,48(r21); /* move DAR to stackframe */ \
+ std r23,_DAR(r1); \
+ ld r22,56(r21); /* move DSISR to stackframe */ \
+ std r22,_DSISR(r1); \
+ lbz r22,PACAPROCENABLED(r20); \
+ std r22,SOFTE(r1); \
+ ld r22,0(r21); /* get SRR0 from exc. frame */ \
+ ld r23,8(r21); /* get SRR1 from exc. frame */ \
+ addi r21,r21,EXC_FRAME_SIZE;/* pop off exception frame */ \
+ std r21,PACAEXCSP(r20); \
+ SAVE_GPR(0, r1); /* save r0 in stackframe */ \
+ SAVE_8GPRS(2, r1); /* save r2 - r13 in stackframe */ \
+ SAVE_4GPRS(10, r1); \
+ ld r2,PACATOC(r20)
+
/*
* Note: code which follows this uses cr0.eq (set if from kernel),
- * r21, r22 (SRR0), and r23 (SRR1).
+ * r1, r22 (SRR0), and r23 (SRR1).
*/
/*
@@ -218,16 +275,25 @@
EXCEPTION_PROLOG_ISERIES; \
b label##_common
+#define MASKABLE_EXCEPTION_ISERIES( label ) \
+ .globl label##_Iseries; \
+label##_Iseries: \
+ EXCEPTION_PROLOG_ISERIES; \
+ lbz r22,PACAPROCENABLED(r20); \
+ cmpi 0,r22,0; \
+ beq- label##_Iseries_masked; \
+ b label##_common
+
#define STD_EXCEPTION_COMMON( trap, label, hdlr ) \
.globl label##_common; \
label##_common: \
EXCEPTION_PROLOG_COMMON; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
- SET_REG_TO_CONST(r20, MSR_KERNEL); \
+ li r20,0; \
li r6,trap; \
- bl .transfer_to_handler; \
- .llong hdlr; \
- .llong .ret_from_except
+ bl .save_remaining_regs; \
+ bl hdlr; \
+ b .ret_from_except
/*
* Start of pSeries system interrupt routines
@@ -253,6 +319,7 @@
STD_EXCEPTION_PSERIES( 0xd00, SingleStep )
STD_EXCEPTION_PSERIES( 0xe00, Trap_0e )
STD_EXCEPTION_PSERIES( 0xf00, PerformanceMonitor )
+ STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint )
. = 0x4000
.globl __end_interupts
@@ -318,11 +385,11 @@
STD_EXCEPTION_ISERIES( DataAccessSLB )
STD_EXCEPTION_ISERIES( InstructionAccess )
STD_EXCEPTION_ISERIES( InstructionAccessSLB )
- STD_EXCEPTION_ISERIES( HardwareInterrupt )
+ MASKABLE_EXCEPTION_ISERIES( HardwareInterrupt )
STD_EXCEPTION_ISERIES( Alignment )
STD_EXCEPTION_ISERIES( ProgramCheck )
STD_EXCEPTION_ISERIES( FPUnavailable )
- STD_EXCEPTION_ISERIES( Decrementer )
+ MASKABLE_EXCEPTION_ISERIES( Decrementer )
STD_EXCEPTION_ISERIES( Trap_0a )
STD_EXCEPTION_ISERIES( Trap_0b )
STD_EXCEPTION_ISERIES( SystemCall )
@@ -362,9 +429,7 @@
/* Let the Hypervisor know we are alive */
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
lis r3,0x8002
- rldicr r0,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
- rldicl r3,r3,0,48 /* r3 = r3 & 0x000000000000ffff */
- or r3,r3,r0 /* r3 = r3 | r0 */
+ rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
#else /* CONFIG_SMP */
/* Yield the processor. This is required for non-SMP kernels
which are running on multi-threaded machines. */
@@ -380,6 +445,30 @@
b 1b /* If SMP not configured, secondaries
* loop forever */
+ .globl HardwareInterrupt_Iseries_masked
+HardwareInterrupt_Iseries_masked:
+ b maskable_exception_exit
+
+ .globl Decrementer_Iseries_masked
+Decrementer_Iseries_masked:
+ li r22,1
+ stb r22,PACALPPACA+LPPACADECRINT(r20)
+ lwz r22,PACADEFAULTDECR(r20)
+ mtspr DEC,r22
+maskable_exception_exit:
+ mtcrf 0xff,r23 /* Restore regs and free exception frame */
+ ld r22,0(r21)
+ ld r23,8(r21)
+ mtspr SRR0,r22
+ mtspr SRR1,r23
+ ld r22,32(r21)
+ ld r23,40(r21)
+ addi r21,r21,EXC_FRAME_SIZE
+ std r21,PACAEXCSP(r20)
+ mfspr r21,SPRG1
+ mfspr r20,SPRG2
+ rfid
+
/*** Common interrupt handlers ***/
STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException )
@@ -390,32 +479,54 @@
STD_EXCEPTION_COMMON( 0xd00, SingleStep, .SingleStepException )
STD_EXCEPTION_COMMON( 0xe00, Trap_0e, .UnknownException )
STD_EXCEPTION_COMMON( 0xf00, PerformanceMonitor, .PerformanceMonitorException )
+ STD_EXCEPTION_COMMON(0x1300, InstructionBreakpoint, .InstructionBreakpointException )
-/* r20 is in SPRG2,
- r21 is in the PACA
-*/
+/*
+ * Return from an exception which is handled without calling
+ * save_remaining_regs. The caller is assumed to have done
+ * EXCEPTION_PROLOG_COMMON.
+ */
+fast_exception_return:
+ ld r3,_CCR(r1)
+ ld r4,_LINK(r1)
+ ld r5,_CTR(r1)
+ ld r6,_XER(r1)
+ mtcr r3
+ mtlr r4
+ mtctr r5
+ mtspr XER,r6
+ REST_GPR(0, r1)
+ REST_8GPRS(2, r1)
+ REST_4GPRS(10, r1)
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+ REST_4GPRS(20, r1)
+ ld r1,GPR1(r1)
+ rfid
+
+
+/*
+ * Here r20 points to the PACA, r21 to the exception frame,
+ * r23 contains the saved CR.
+ * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ */
.globl DataAccess_common
DataAccess_common:
- mfcr r20
- mfspr r21,DAR
- srdi r21,r21,60
- cmpi 0,r21,0xc
- bne 3f
+ mfspr r22,DAR
+ srdi r22,r22,60
+ cmpi 0,r22,0xc
- /* Segment faulted on a bolted segment. Go off and map that segment. */
- b .do_stab_bolted
+ /* Segment fault on a bolted segment. Go off and map that segment. */
+ beq .do_stab_bolted
-3: mtcr r20
EXCEPTION_PROLOG_COMMON
- mfspr r20,DSISR
- std r20,_DSISR(r21)
- andis. r0,r20,0xa450 /* weird error? */
+ ld r3,_DSISR(r1)
+ andis. r0,r3,0xa450 /* weird error? */
bne 1f /* if not, try to put a PTE */
- mfspr r3,DAR /* into the hash table */
- std r3,_DAR(r21)
- rlwinm r4,r20,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */
+ andis. r0,r3,0x0020 /* Is it a page table fault? */
+ rlwinm r4,r3,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */
+ ld r3,_DAR(r1) /* into the hash table */
- andis. r0,r20,0x0020 /* Is it a page table fault? */
beq 2f /* If so handle it */
li r4,0x300 /* Trap number */
bl .do_stab_SI
@@ -423,60 +534,44 @@
2: bl .do_hash_page_DSI /* Try to handle as hpte fault */
1:
- ld r4,_DAR(r21)
- ld r5,_DSISR(r21)
+ ld r4,_DAR(r1)
+ ld r5,_DSISR(r1)
addi r3,r1,STACK_FRAME_OVERHEAD
-
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1) /* Copy saved SOFTE bit */
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0x300
- bl .transfer_to_handler
- .llong .do_page_fault
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
.globl DataAccessSLB_common
DataAccessSLB_common:
+ mfspr r22,DAR
+ srdi r22,r22,60
+ cmpi 0,r22,0xc
+
+ /* Segment fault on a bolted segment. Go off and map that segment. */
+ beq .do_slb_bolted
+
EXCEPTION_PROLOG_COMMON
- mfspr r3,DAR
+ ld r3,_DAR(r1)
li r4,0x380 /* Exception vector */
bl .ste_allocate
or. r3,r3,r3 /* Check return code */
- bne 1f /* Branch on failure */
-
- /* SLB Allocation success - Return. */
- ld r3,_CCR(r21)
- ld r4,_LINK(r21)
- ld r5,_CTR(r21)
- ld r6,_XER(r21)
-
- mtcrf 0xff,r3
- mtlr r4
- mtctr r5
- mtspr XER,r6
- REST_8GPRS(0,r21)
- REST_4GPRS(8,r21)
- REST_2GPRS(12,r21)
- mtspr SRR1,r23
- mtspr SRR0,r22
- ld r20,GPR20(r21)
- ld r22,GPR22(r21)
- ld r23,GPR23(r21)
- ld r21,GPR21(r21)
- RFID
-
-1:
- mfspr r4,DAR
- std r4,_DAR(r21)
- mfspr r5,DSISR
- std r5,_DSISR(r21)
+ beq fast_exception_return /* Return if we succeeded */
addi r3,r1,STACK_FRAME_OVERHEAD
-
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0x380
- bl .transfer_to_handler
- .llong .do_page_fault
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
.globl InstructionAccess_common
InstructionAccess_common:
@@ -497,12 +592,15 @@
mr r4,r22
mr r5,r23
addi r3,r1,STACK_FRAME_OVERHEAD
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0x400
- bl .transfer_to_handler
- .llong .do_page_fault
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
.globl InstructionAccessSLB_common
InstructionAccessSLB_common:
@@ -511,89 +609,67 @@
li r4,0x480 /* Exception vector */
bl .ste_allocate
or. r3,r3,r3 /* Check return code */
- bne 1f /* Branch on failure */
+ beq fast_exception_return /* Return if we succeeded */
- /* SLB Allocation success - Return. */
- ld r3,_CCR(r21)
- ld r4,_LINK(r21)
- ld r5,_CTR(r21)
- ld r6,_XER(r21)
-
- mtcrf 0xff,r3
- mtlr r4
- mtctr r5
- mtspr XER,r6
- REST_8GPRS(0,r21)
- REST_4GPRS(8,r21)
- REST_2GPRS(12,r21)
- mtspr SRR1,r23
- mtspr SRR0,r22
- ld r20,GPR20(r21)
- ld r22,GPR22(r21)
- ld r23,GPR23(r21)
- ld r21,GPR21(r21)
- RFID
-
-1:
- mfspr r4,DAR
- std r4,_DAR(r21)
- mfspr r5,DSISR
- std r5,_DSISR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
-
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0x380
- bl .transfer_to_handler
- .llong .do_page_fault
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .do_page_fault
+ b .ret_from_except
.globl HardwareInterrupt_common
HardwareInterrupt_common:
EXCEPTION_PROLOG_COMMON
HardwareInterrupt_entry:
addi r3,r1,STACK_FRAME_OVERHEAD
- SET_REG_TO_CONST(r20, MSR_KERNEL)
+ li r20,0
li r6,0x500
- bl .transfer_to_handler
- .llong .do_IRQ
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .do_IRQ
+ b .ret_from_except
.globl Alignment_common
Alignment_common:
EXCEPTION_PROLOG_COMMON
- mfspr r4,DAR
- std r4,_DAR(r21)
- mfspr r5,DSISR
- std r5,_DSISR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0x600
- bl .transfer_to_handler
- .llong .AlignmentException
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .AlignmentException
+ b .ret_from_except
.globl ProgramCheck_common
ProgramCheck_common:
EXCEPTION_PROLOG_COMMON
addi r3,r1,STACK_FRAME_OVERHEAD
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0x700
- bl .transfer_to_handler
- .llong .ProgramCheckException
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .ProgramCheckException
+ b .ret_from_except
.globl FPUnavailable_common
FPUnavailable_common:
EXCEPTION_PROLOG_COMMON
bne .load_up_fpu /* if from user, just load it up */
- SET_REG_TO_CONST(r20, MSR_KERNEL)
+ li r20,0
li r6,0x800
- bl .transfer_to_handler /* if from kernel, take a trap */
- .llong .KernelFP
- .llong .ret_from_except
+ bl .save_remaining_regs /* if from kernel, take a trap */
+ bl .KernelFP
+ b .ret_from_except
.globl SystemCall_common
SystemCall_common:
@@ -605,13 +681,16 @@
beq+ HardwareInterrupt_entry
1:
#endif
- std r3,ORIG_GPR3(r21)
- SET_REG_TO_CONST(r20, MSR_KERNEL)
- rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ std r3,ORIG_GPR3(r1)
+#ifdef DO_SOFT_DISABLE
+ ld r20,SOFTE(r1)
+#else
+ rldicl r20,r23,49,63 /* copy EE bit from saved MSR */
+#endif
li r6,0xC00
- bl .transfer_to_handler
- .llong .DoSyscall
- .llong .ret_from_except
+ bl .save_remaining_regs
+ bl .DoSyscall
+ b .ret_from_except
_GLOBAL(do_hash_page_ISI)
li r4,0
@@ -620,7 +699,21 @@
ori r4,r4,1 /* add _PAGE_PRESENT */
mflr r21 /* Save LR in r21 */
- /* r21 restored later from r1 */
+
+#ifdef DO_SOFT_DISABLE
+ /*
+ * We hard enable here (but first soft disable) so that the hash_page
+ * code can spin on the hash_table_lock with problem on a shared
+ * processor.
+ */
+ li r0,0
+ stb r0,PACAPROCENABLED(r20) /* Soft Disabled */
+
+ mfmsr r0
+ ori r0,r0,MSR_EE
+ mtmsrd r0 /* Hard Enable */
+#endif
+
/*
* r3 contains the faulting address
* r4 contains the required access permissions
@@ -629,58 +722,61 @@
*/
bl .hash_page /* build HPTE if possible */
- mtlr r21 /* restore LR */
- mr r21,r1 /* restore r21 */
-
- or. r3,r3,r3 /* Check return code */
- bnelr /* Return to DSI or ISI on failure */
+#ifdef DO_SOFT_DISABLE
/*
- * The HPTE has been created/updated. Restore and retry the faulting inst
+ * Now go back to hard disabled.
*/
+ mfmsr r0
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r0,r0,r4
+ mtmsrd r0 /* Hard Disable */
+
+ ld r0,SOFTE(r1)
+ cmpdi 0,r0,0 /* See if we will soft enable in */
+ /* save_remaining_regs */
+ beq 5f
+ CHECKANYINT(r4,r5)
+ bne- HardwareInterrupt_entry /* Convert this DSI into an External */
+ /* to process interrupts which occurred */
+ /* during hash_page */
+5:
+ stb r0,PACAPROCENABLED(r20) /* Restore soft enable/disable status */
+#endif
+ or. r3,r3,r3 /* Check return code */
+ beq fast_exception_return /* Return from exception on success */
- ld r3,_CCR(r21)
- ld r4,_LINK(r21)
- ld r5,_CTR(r21)
- ld r6,_XER(r21)
- mtcrf 0xff,r3
- mtlr r4
- mtctr r5
- mtspr XER,r6
- REST_8GPRS(0,r21)
- REST_4GPRS(8,r21)
- REST_2GPRS(12,r21)
- mtspr SRR1,r23
- mtspr SRR0,r22
- ld r20,GPR20(r21)
- ld r22,GPR22(r21)
- ld r23,GPR23(r21)
- ld r21,GPR21(r21)
- rfid
+ mtlr r21 /* restore LR */
+ blr /* Return to DSI or ISI on failure */
-/* orig r20 is in SPRG2,
- orig r21 is in the PACA
- r20 contains CCR
-
- r22 needs to be saved
- r1 needs to be saved
- CCR needs to be saved
-*/
+/*
+ * r20 points to the PACA, r21 to the exception frame,
+ * r23 contains the saved CR.
+ * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * We assume we aren't going to take any exceptions during this procedure.
+ */
_GLOBAL(do_stab_bolted)
- mfsprg r21,3
- std r22,PACAR22(r21)
- std r1,PACAR1(r21)
- stw r20,PACACCR(r21)
- mfspr r21,DAR
+ std r23,48(r21) /* save CR in exc. frame */
+ mfspr r21,DSISR
+ andis. r21,r21,0x0020
+ bne+ 2f
+ li r3,0
+#ifdef CONFIG_XMON
+ bl .xmon
+#endif
+1: b 1b
+2:
/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
+ mfspr r21,DAR
rldicl r20,r21,36,32 /* Permits a full 32b of ESID */
rldicr r20,r20,15,48
rldicl r21,r21,4,60
or r20,r20,r21
li r21,9 /* VSID_RANDOMIZER */
- rldicr r21,r21,32,31
+ sldi r21,r21,32
oris r21,r21,58231
ori r21,r21,39831
@@ -699,20 +795,20 @@
/* Search the primary group for a free entry */
li r22,0
1:
- ld r1,0(r21) /* Test valid bit of the current ste */
- rldicl r1,r1,57,63
- cmpwi r1,0
+ ld r23,0(r21) /* Test valid bit of the current ste */
+ rldicl r23,r23,57,63
+ cmpwi r23,0
bne 2f
- ld r1,8(r21) /* Get the current vsid part of the ste */
- rldimi r1,r20,12,0 /* Insert the new vsid value */
- std r1,8(r21) /* Put new entry back into the stab */
+ ld r23,8(r21) /* Get the current vsid part of the ste */
+ rldimi r23,r20,12,0 /* Insert the new vsid value */
+ std r23,8(r21) /* Put new entry back into the stab */
eieio /* Order vsid update */
- ld r1,0(r21) /* Get the esid part of the ste */
+ ld r23,0(r21) /* Get the esid part of the ste */
mfspr r20,DAR /* Get the new esid */
rldicl r20,r20,36,28 /* Permits a full 36b of ESID */
- rldimi r1,r20,28,0 /* Insert the new esid value */
- ori r1,r1,144 /* Turn on valid and kp */
- std r1,0(r21) /* Put new entry back into the stab */
+ rldimi r23,r20,28,0 /* Insert the new esid value */
+ ori r23,r23,144 /* Turn on valid and kp */
+ std r23,0(r21) /* Put new entry back into the stab */
sync /* Order the update */
b 3f
2:
@@ -732,27 +828,27 @@
/* r21 currently points to and ste one past the group of interest */
/* make it point to the randomly selected entry */
subi r21,r21,128
- ori r21,r21,r22 /* r21 is the entry to invalidate */
+ or r21,r21,r22 /* r21 is the entry to invalidate */
isync /* mark the entry invalid */
- ld r1,0(r21)
+ ld r23,0(r21)
li r22,-129
- and r1,r1,r22
- std r1,0(r21)
+ and r23,r23,r22
+ std r23,0(r21)
sync
- ld r1,8(r21)
- rldimi r1,r20,12,0
- std r1,8(r21)
+ ld r23,8(r21)
+ rldimi r23,r20,12,0
+ std r23,8(r21)
eieio
- ld r1,0(r21) /* Get the esid part of the ste */
- mr r22,r1
- mfspr r20,DAR /* Get the new esid */
- rldicl r20,r20,36,32 /* Permits a full 32b of ESID */
- rldimi r1,r20,28,0 /* Insert the new esid value */
- ori r1,r1,144 /* Turn on valid and kp */
- std r1,0(r21) /* Put new entry back into the stab */
+ ld r23,0(r21) /* Get the esid part of the ste */
+ mr r22,r23
+ mfspr r20,DAR /* Get the new esid */
+ rldicl r20,r20,36,32 /* Permits a full 32b of ESID */
+ rldimi r23,r20,28,0 /* Insert the new esid value */
+ ori r23,r23,144 /* Turn on valid and kp */
+ std r23,0(r21) /* Put new entry back into the stab */
rldicl r22,r22,36,28
rldicr r22,r22,28,35
@@ -761,24 +857,108 @@
3:
/* All done -- return from exception. */
- mfsprg r20,3 /* Load the PACA pointer */
+ mfsprg r20,3 /* Load the PACA pointer */
+ ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */
+ addi r22,r21,EXC_FRAME_SIZE
+ ld r23,48(r21) /* get saved CR */
+ std r22,PACAEXCSP(r20) /* pop off the exception frame */
+ mtcr r23 /* restore CR */
+ ld r22,0(r21) /* Get SRR0 from exc. frame */
+ ld r23,8(r21) /* Get SRR1 from exc. frame */
+ mtspr SRR0,r22
+
+ mtspr SRR1,r23
+ ld r20,16(r21) /* restore r20 from exc. frame */
+ ld r22,32(r21) /* restore r22 and r23 */
+ ld r23,40(r21)
+ ld r21,24(r21) /* restore r21 last */
+ rfid
+_TRACEBACK(do_stab_bolted)
+
+/*
+ * r20 points to the PACA, r21 to the exception frame,
+ * r23 contains the saved CR.
+ * r20 - r23, SRR0 and SRR1 are saved in the exception frame.
+ * We assume we aren't going to take any exceptions during this procedure.
+ */
+_GLOBAL(do_slb_bolted)
+ std r23,48(r21) /* save CR in exc. frame */
- ld r22,LPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */
- ld r21,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */
- mtspr SRR1,r21
+ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
+ mfspr r21,DAR
+ rldicl r20,r21,36,32 /* Permits a full 32b of ESID */
+ rldicr r20,r20,15,48
+ rldicl r21,r21,4,60
+ or r20,r20,r21
+
+ li r21,9 /* VSID_RANDOMIZER */
+ sldi r21,r21,32
+ oris r21,r21,58231
+ ori r21,r21,39831
+
+ mulld r20,r20,r21
+ clrldi r20,r20,28 /* r20 = vsid */
+
+ /* Search the SLB for a free entry */
+ li r22,1
+1:
+ slbmfee r23,r22
+ rldicl r23,r23,37,63
+ cmpwi r23,0
+ beq 3f /* Found an invalid entry */
+
+ addi r22,r22,1
+ cmpldi r22,64
+ blt 1b
+
+ /* Didn't find a free entry -- for now trap out. Do castouts later DRENG */
+ li r3,0
+#ifdef CONFIG_XMON
+ bl .xmon
+#endif
+2: b 2b
+
+ /* r20 = vsid, r22 = entry */
+3:
+ /* Put together the vsid portion of the entry. */
+ li r21,0
+ rldimi r21,r20,12,0
+ ori r20,r21,1024
+
+ /* Put together the esid portion of the entry. */
+ mfspr r21,DAR /* Get the new esid */
+ rldicl r21,r21,36,28 /* Permits a full 36b of ESID */
+ li r23,0
+ rldimi r23,r21,28,0 /* Insert esid */
+ oris r21,r23,2048 /* valid bit */
+ rldimi r21,r22,0,52 /* Insert entry */
+
+ isync
+ slbmte r20,r21
+ isync
+
+ /* All done -- return from exception. */
+ mfsprg r20,3 /* Load the PACA pointer */
+ ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */
+ addi r22,r21,EXC_FRAME_SIZE
+ ld r23,48(r21) /* get saved CR */
+ std r22,PACAEXCSP(r20) /* pop off the exception frame */
+ mtcr r23 /* restore CR */
+ ld r22,0(r21) /* Get SRR0 from exc. frame */
+ ld r23,8(r21) /* Get SRR1 from exc. frame */
mtspr SRR0,r22
- lwz r21,PACACCR(r20) /* Restore the clobbered regs */
- mtcr r21
- ld r1, PACAR1(r20)
- ld r21,PACAR21(r20)
- ld r22,PACAR22(r20)
- mfspr r20,SPRG2
+ mtspr SRR1,r23
+ ld r20,16(r21) /* restore r20 from exc. frame */
+ ld r22,32(r21) /* restore r22 and r23 */
+ ld r23,40(r21)
+ ld r21,24(r21) /* restore r21 last */
rfid
+_TRACEBACK(do_slb_bolted)
_GLOBAL(do_stab_SI)
mflr r21 /* Save LR in r21 */
- /* r21 restored later from r1 */
+
/*
* r3 contains the faulting address
* r4 contains the required access permissions
@@ -787,108 +967,72 @@
*/
bl .ste_allocate /* build STE if possible */
- mtlr r21 /* restore LR */
- mr r21,r1 /* restore r21 */
-
or. r3,r3,r3 /* Check return code */
- bnelr /* Return to DSI or ISI on failure */
+ beq fast_exception_return /* Return from exception on success */
+ mtlr r21 /* restore LR */
+ blr /* Return to DSI or ISI on failure */
- /*
- * The STE has been created/updated. Restore and retry the faulting inst
- */
-
- ld r3,_CCR(r21)
- ld r4,_LINK(r21)
- ld r5,_CTR(r21)
- ld r6,_XER(r21)
-
- mtcrf 0xff,r3
- mtlr r4
- mtctr r5
- mtspr XER,r6
- REST_8GPRS(0,r21)
- REST_4GPRS(8,r21)
- REST_2GPRS(12,r21)
- mtspr SRR1,r23
- mtspr SRR0,r22
- ld r20,GPR20(r21)
- ld r22,GPR22(r21)
- ld r23,GPR23(r21)
- ld r21,GPR21(r21)
- rfid
-
-/*
- * This code finishes saving the registers to the exception frame
- * and jumps to the appropriate handler for the exception. Address
- * translation is already on.
- */
-_GLOBAL(transfer_to_handler)
-/*
- * Save the rest of the registers into the pt_regs structure
- */
- std r22,_NIP(r21)
- std r23,_MSR(r21)
- std r6,TRAP(r21)
- ld r6,GPR6(r21)
- SAVE_2GPRS(14, r21)
- SAVE_4GPRS(16, r21)
- SAVE_8GPRS(24, r21)
/*
- * Clear the RESULT field
+ * This code finishes saving the registers to the exception frame.
+ * Address translation is already on.
*/
+_GLOBAL(save_remaining_regs)
+ /*
+ * Save the rest of the registers into the pt_regs structure
+ */
+ std r22,_NIP(r1)
+ std r23,_MSR(r1)
+ std r6,TRAP(r1)
+ ld r6,GPR6(r1)
+ SAVE_2GPRS(14, r1)
+ SAVE_4GPRS(16, r1)
+ SAVE_8GPRS(24, r1)
+
+ /*
+ * Clear the RESULT field
+ */
li r22,0
- std r22,RESULT(r21)
-/*
- * Test if from user state; result will be tested later
- */
+ std r22,RESULT(r1)
+
+ /*
+ * Test if from user state; result will be tested later
+ */
andi. r23,r23,MSR_PR /* Set CR for later branch */
-/*
- * Indicate that r1 contains the kernel stack and
- * get the Kernel TOC and CURRENT pointers from the Paca
- */
+
+ /*
+ * Indicate that r1 contains the kernel stack and
+ * get the Kernel TOC and CURRENT pointers from the Paca
+ */
mfspr r23,SPRG3 /* Get PACA */
std r22,PACAKSAVE(r23) /* r1 is now kernel sp */
ld r2,PACATOC(r23) /* Get Kernel TOC pointer */
ld r22,PACACURRENT(r23) /* Get CURRENT */
-/*
- * If from user state, update THREAD.regs
- */
+
+ /*
+ * If from user state, update THREAD.regs
+ */
beq 2f /* Modify THREAD.regs if from user */
addi r24,r1,STACK_FRAME_OVERHEAD
std r24,THREAD+PT_REGS(r22)
2:
-/*
- * Since we store 'current' in the PACA now, we don't need to
- * set it here. When r2 was used as 'current' it had to be
- * set here because it could have been changed by the user.
- */
+ /*
+ * Since we store 'current' in the PACA now, we don't need to
+ * set it here. When r2 was used as 'current' it had to be
+ * set here because it could have been changed by the user.
+ */
-/*
- * Check for kernel stack overflow
- */
- addi r24,r22,TASK_STRUCT_SIZE /* check for kernel stack overflow */
- cmpld 0,r1,r22
- cmpld 1,r1,r24
- crand 1,1,4
- bgt- .stack_ovf /* if r22 < r1 < r22+TASK_STRUCT_SIZE */
-
-/*
- * Get the handler address and its return address and
- * rfid to the handler
- */
-/* MIKEC: Do we really need to rfid here? Since we are already running
- with relocate on, could we just branch to the handler?
- We also will be turning on MSR.EE for some interrupts here
-*/
- mflr r23
- ld r24,0(r23) /* virtual address of handler */
- ld r23,8(r23) /* where to go when done */
- mtspr SRR0,r24
- mtspr SRR1,r20
- mtlr r23
- rfid /* jump to handler */
+ SET_REG_TO_CONST(r22, MSR_KERNEL)
+
+#ifdef DO_SOFT_DISABLE
+ stb r20,PACAPROCENABLED(r23) /* possibly soft enable */
+ ori r22,r22,MSR_EE /* always hard enable */
+#else
+ rldimi r22,r20,15,48 /* Insert desired EE value */
+#endif
+
+ mtmsrd r22
+ blr
-#ifdef CONFIG_SMP
/*
* On pSeries, secondary processors spin in the following code.
* At entry, r3 = this processor's number (in Linux terms, not hardware).
@@ -918,11 +1062,12 @@
ldx r1,r3,r28
cmpi 0,r23,0
+#ifdef CONFIG_SMP
#ifdef SECONDARY_PROCESSORS
bne .__secondary_start
#endif
+#endif
b 1b /* Loop until told to go */
-#endif /* CONFIG_SMP */
_GLOBAL(__start_initialization_iSeries)
@@ -1106,20 +1251,6 @@
copy_to_here:
/*
- * On kernel stack overflow, load up an initial stack pointer
- * and call StackOverflow(regs), which should not return.
- */
-_STATIC(stack_ovf)
- addi r3,r1,STACK_FRAME_OVERHEAD
- LOADADDR(r1,init_task_union)
- addi r1,r1,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
- LOADADDR(r24,StackOverflow)
- SET_REG_TO_CONST(r20, MSR_KERNEL);
- mtspr SRR0,r24
- mtspr SRR1,r20
- rfid
-
-/*
* Disable FP for the task which had the FPU previously,
* and save its floating-point registers in its thread_struct.
* Enables the FPU for use in the kernel on return.
@@ -1130,7 +1261,7 @@
mfmsr r5 /* grab the current MSR */
ori r5,r5,MSR_FP
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
@@ -1166,19 +1297,7 @@
std r4,last_task_used_math@l(r3)
#endif /* CONFIG_SMP */
/* restore registers and return */
- ld r3,_CCR(r21)
- ld r4,_LINK(r21)
- mtcrf 0xff,r3
- mtlr r4
- REST_2GPRS(1, r21)
- REST_4GPRS(3, r21)
- /* we haven't used ctr or xer */
- mtspr SRR1,r23
- mtspr SRR0,r22
- REST_GPR(20, r21)
- REST_2GPRS(22, r21)
- ld r21,GPR21(r21)
- rfid
+ b fast_exception_return
/*
* FP unavailable trap from kernel - print a message, but let
@@ -1206,7 +1325,7 @@
mfmsr r5
ori r5,r5,MSR_FP
mtmsrd 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 */
@@ -1255,6 +1374,7 @@
std r2,PACATOC(r25)
li r6,0
std r6,PACAKSAVE(r25)
+ stb r6,PACAPROCENABLED(r25)
#ifndef CONFIG_PPC_ISERIES
/* Initialize the page table pointer register. */
@@ -1295,6 +1415,9 @@
/* enable MMU and jump to start_secondary */
LOADADDR(r3,.start_secondary)
SET_REG_TO_CONST(r4, MSR_KERNEL)
+#ifdef DO_SOFT_DISABLE
+ ori r4,r4,MSR_EE
+#endif
mtspr SRR0,r3
mtspr SRR1,r4
rfid
@@ -1312,7 +1435,7 @@
rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
or r11,r11,r12
mtmsrd r11
- SYNC
+ isync
blr
/*
@@ -1327,7 +1450,7 @@
rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
andc r11,r11,r12
mtmsrd r11
- SYNC
+ isync
blr
@@ -1466,14 +1589,6 @@
std r2,PACATOC(r4)
li r5,0
std r0,PACAKSAVE(r4)
-/*
- * Register old definition new definition
- *
- * SPRG0 temp - used to save gpr reserved for hypervisor
- * SPRG1 temp - used to save gpr unused
- * SPRG2 0 or kernel stack frame temp - used to save gpr
- * SPRG3 Linux thread virt addr of Paca
- */
/*
* Restore the parms passed in from the bootloader.
@@ -1488,6 +1603,15 @@
/* Load up the kernel context */
5:
+#ifdef DO_SOFT_DISABLE
+ mfspr r4,SPRG3
+ li r5,0
+ stb r5,PACAPROCENABLED(r4) /* Soft Disabled */
+ mfmsr r5
+ ori r5,r5,MSR_EE /* Hard Enabled */
+ mtmsrd r5
+#endif
+
bl .start_kernel
/*
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/htab.c linuxppc64_2_4/arch/ppc64/kernel/htab.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/htab.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/htab.c Mon Sep 17 16:41:18 2001
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
/* For iSeries */
@@ -47,7 +48,7 @@
* HPTE --> PowerPC Hashed Page Table Entry
*/
-HTAB htab_data = {NULL, NULL, 0, 0, 0};
+HTAB htab_data = {NULL, 0, 0, 0, 0};
static ssize_t ppc_htab_read(struct file * file, char * buf,
size_t count, loff_t *ppos);
@@ -72,8 +73,6 @@
extern inline void make_ste(unsigned long stab,
unsigned long esid, unsigned long vsid);
-extern pgd_t * bolted_pgd;
-
extern char _stext[], _etext[], __start_naca[], __end_stab[];
static spinlock_t hash_table_lock = SPIN_LOCK_UNLOCKED;
@@ -83,6 +82,7 @@
#define RELOC(x) (*PTRRELOC(&(x)))
extern unsigned long htab_size( unsigned long );
+unsigned long hpte_getword0_iSeries( unsigned long slot );
static inline void
create_pte_mapping(unsigned long start, unsigned long end,
@@ -113,24 +113,36 @@
* Calculate the required size of the htab. We want the number of
* PTEGs to equal one half the number of real pages.
*/
- htab_size_bytes = htab_size(_naca->physicalMemorySize);
+ htab_size_bytes = 1UL << _naca->pftSize;
pteg_count = htab_size_bytes >> 7;
- _htab_data->htab_num_ptegs = pteg_count;
- _htab_data->htab_hash_mask = pteg_count - 1;
- /* Find storage for the HPT. Must be contiguous in
- * the absolute address space.
- */
- table = lmb_alloc(htab_size_bytes, htab_size_bytes);
- if ( !table )
- panic("ERROR, cannot find space for HPTE\n");
- _htab_data->htab = (HPTE *)__a2v(table);
+ /* For debug, make the HTAB 1/8 as big as it normally would be. */
+ ifppcdebug(PPCDBG_HTABSIZE) {
+ pteg_count >>= 3;
+ htab_size_bytes = pteg_count << 7;
+ }
- /* htab absolute addr + encoded htabsize */
- RELOC(_SDR1) = table + __ilog2(pteg_count) - 11;
+ _htab_data->htab_num_ptegs = pteg_count;
+ _htab_data->htab_hash_mask = pteg_count - 1;
- /* Initialize the HPT with no entries */
- cacheable_memzero((void *)table, htab_size_bytes);
+ if(_machine == _MACH_pSeries) {
+ /* Find storage for the HPT. Must be contiguous in
+ * the absolute address space.
+ */
+ table = lmb_alloc(htab_size_bytes, htab_size_bytes);
+ if ( !table )
+ panic("ERROR, cannot find space for HPTE\n");
+ _htab_data->htab = (HPTE *)__a2v(table);
+
+ /* htab absolute addr + encoded htabsize */
+ RELOC(_SDR1) = table + __ilog2(pteg_count) - 11;
+
+ /* Initialize the HPT with no entries */
+ cacheable_memzero((void *)table, htab_size_bytes);
+ } else {
+ _htab_data->htab = NULL;
+ RELOC(_SDR1) = 0;
+ }
mode_ro = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RXRX;
mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
@@ -194,44 +206,42 @@
for(;x;x|=1);
}
-void invalidate_hpte( unsigned long slot )
+/* Functions to invalidate a HPTE */
+static void hpte_invalidate_iSeries( unsigned long slot )
{
+ HvCallHpt_invalidateSetSwBitsGet( slot, 0, 0 );
+}
- /* Invalidate the HPTE */
-
- if ( _machine == _MACH_iSeries ) {
- HvCallHpt_invalidateSetSwBitsGet( slot, 0, 0 );
- }
- else {
- /* Local copy of the first doubleword of the HPTE */
- union {
- unsigned long d;
- Hpte_dword0 h;
- } hpte_dw0;
+static void hpte_invalidate_pSeries( unsigned long slot )
+{
+ /* Local copy of the first doubleword of the HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
- /* Locate the HPTE */
- HPTE * hptep = htab_data.htab + slot;
+ /* Locate the HPTE */
+ HPTE * hptep = htab_data.htab + slot;
- /* Get the first doubleword of the HPTE */
- hpte_dw0.d = hptep->dw0.dword0;
-
- /* Invalidate the hpte */
- hptep->dw0.dword0 = 0;
+ /* Get the first doubleword of the HPTE */
+ hpte_dw0.d = hptep->dw0.dword0;
- /* Invalidate the tlb */
- {
- unsigned long vsid, group, pi, pi_high;
-
- vsid = hpte_dw0.h.avpn >> 5;
- group = slot >> 3;
- if(hpte_dw0.h.h) {
- group = ~group;
- }
- pi = (vsid ^ group) & 0x7ff;
- pi_high = (hpte_dw0.h.avpn & 0x1f) << 11;
- pi |= pi_high;
- _tlbie(pi << 12);
- }
+ /* Invalidate the hpte */
+ hptep->dw0.dword0 = 0;
+
+ /* Invalidate the tlb */
+ {
+ unsigned long vsid, group, pi, pi_high;
+
+ vsid = hpte_dw0.h.avpn >> 5;
+ group = slot >> 3;
+ if(hpte_dw0.h.h) {
+ group = ~group;
+ }
+ pi = (vsid ^ group) & 0x7ff;
+ pi_high = (hpte_dw0.h.avpn & 0x1f) << 11;
+ pi |= pi_high;
+ _tlbie(pi << 12);
}
}
@@ -240,48 +250,72 @@
* return slot index (if in primary group)
* return -slot index (if in secondary group)
*/
-long select_hpte_slot( unsigned long vpn )
+static long hpte_selectslot_iSeries( unsigned long vpn )
{
-
-/****** Add code for iSeries ******/
-
- HPTE * hptep;
HPTE hpte;
+ long ret_slot, orig_slot;
unsigned long primary_hash;
unsigned long hpteg_slot;
- long ret_slot, orig_slot;
+ unsigned long slot;
unsigned i, k;
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
- if ( _machine == _MACH_iSeries ) {
- ret_slot = orig_slot = HvCallHpt_findValid( &hpte, vpn );
- if ( hpte.dw0.dw0.v ) { /* If valid ...what do we do now? */
- udbg_printf( "select_hpte_slot: vpn 0x%016lx already valid at slot 0x%016lx\n", vpn, ret_slot );
- udbg_printf( "select_hpte_slot: returned hpte 0x%016lx 0x%016lx\n", hpte.dw0.dword0, hpte.dw1.dword1 );
-
- return (0x8000000000000000);
-/* panic("select_hpte_slot found entry already valid\n"); */
- }
- if ( ret_slot == -1 ) { /* -1 indicates no available slots */
- /*
- * Eventually we will have a hypervisor call which will allow us to conditionally
- * invalidate an hpte depending on whether it is bolted. For now, we need to look
- * each entry to see if it is bolted before we invalidate it.
- */
-
-
- /* ADD CODE HERE */
- /* add code to cast out a non-bolted hpte */
- }
- else {
- if ( ret_slot < 0 ) {
- ret_slot &= 0x7fffffffffffffff;
- ret_slot = -ret_slot;
+ ret_slot = orig_slot = HvCallHpt_findValid( &hpte, vpn );
+ if ( hpte.dw0.dw0.v ) { /* If valid ...what do we do now? */
+ udbg_printf( "hpte_selectslot_iSeries: vpn 0x%016lx already valid at slot 0x%016lx\n", vpn, ret_slot );
+ udbg_printf( "hpte_selectslot_iSeries: returned hpte 0x%016lx 0x%016lx\n", hpte.dw0.dword0, hpte.dw1.dword1 );
+
+ return (0x8000000000000000);
+ /* panic("select_hpte_slot found entry already valid\n"); */
+ }
+ if ( ret_slot == -1 ) { /* -1 indicates no available slots */
+
+ /* No available entry found in secondary group */
+
+ PMC_SW_SYSTEM(htab_capacity_castouts);
+
+ primary_hash = hpt_hash( vpn );
+ hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
+ k = htab_data.next_round_robin++ & 0x7;
+
+ for ( i=0; idw0.dword0;
- }
+ HPTE hpte;
+ HvCallHpt_get( &hpte, slot );
+ dword0 = hpte.dw0.dword0;
+
+ return dword0;
+}
+
+unsigned long hpte_getword0_pSeries( unsigned long slot )
+{
+ unsigned long dword0;
+ HPTE * hptep = htab_data.htab + slot;
+ dword0 = hptep->dw0.dword0;
return dword0;
}
-long find_hpte( unsigned long vpn )
+static long hpte_find_iSeries(unsigned long vpn)
{
HPTE hpte;
long slot;
- if ( _machine == _MACH_iSeries ) {
- slot = HvCallHpt_findValid( &hpte, vpn );
- if ( hpte.dw0.dw0.v ) {
- if ( slot < 0 ) {
- slot &= 0x7fffffffffffffff;
- slot = -slot;
- }
+ slot = HvCallHpt_findValid( &hpte, vpn );
+ if ( hpte.dw0.dw0.v ) {
+ if ( slot < 0 ) {
+ slot &= 0x7fffffffffffffff;
+ slot = -slot;
}
- else
- slot = -1;
- }
- else {
- union {
- unsigned long d;
- Hpte_dword0 h;
- } hpte_dw0;
- unsigned long hash;
- unsigned long i,j;
+ } else
+ slot = -1;
+ return slot;
+}
- hash = hpt_hash( vpn );
- for ( j=0; j<2; ++j ) {
- slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
- for ( i=0; i> 11 ) ) &&
- ( hpte_dw0.h.v ) &&
- ( hpte_dw0.h.h == j ) ) {
- /* HPTE matches */
- if ( j )
- slot = -slot;
- return slot;
- }
- ++slot;
+static long hpte_find_pSeries(unsigned long vpn)
+{
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+ long slot;
+ unsigned long hash;
+ unsigned long i,j;
+
+ hash = hpt_hash( vpn );
+ for ( j=0; j<2; ++j ) {
+ slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+ for ( i=0; i> 11 ) ) &&
+ ( hpte_dw0.h.v ) &&
+ ( hpte_dw0.h.h == j ) ) {
+ /* HPTE matches */
+ if ( j )
+ slot = -slot;
+ return slot;
}
- hash = ~hash;
+ ++slot;
}
- slot = -1;
+ hash = ~hash;
}
- return slot;
+ return -1;
}
/* This function is called by btmalloc to bolt an entry in the hpt */
@@ -421,7 +458,7 @@
spin_lock_irqsave( &hash_table_lock, flags );
- hpte_slot = select_hpte_slot( vpn );
+ hpte_slot = ppc_md.hpte_selectslot( vpn );
hash = 0;
if ( hpte_slot < 0 ) {
if ( hpte_slot == 0x8000000000000000 ) {
@@ -434,7 +471,7 @@
hash = 1;
hpte_slot = -hpte_slot;
}
- create_valid_hpte( hpte_slot, vpn, pa >> 12, hash, ptep,
+ ppc_md.hpte_create_valid( hpte_slot, vpn, pa >> 12, hash, ptep,
hpteflags, bolted );
if ( ptep ) {
@@ -465,10 +502,10 @@
* The HPTE is set with the vpn, rpn (converted to absolute)
* and flags
*/
-void create_valid_hpte(unsigned long slot, unsigned long vpn,
- unsigned long prpn, unsigned hash,
- void * ptep, unsigned hpteflags,
- unsigned bolted )
+static void hpte_create_valid_iSeries(unsigned long slot, unsigned long vpn,
+ unsigned long prpn, unsigned hash,
+ void * ptep, unsigned hpteflags,
+ unsigned bolted )
{
/* Local copy of HPTE */
struct {
@@ -500,33 +537,64 @@
lhpte.dw0.h.v = 1;
/* Now fill in the actual HPTE */
+ HvCallHpt_addValidate( slot, hash, (HPTE *)&lhpte );
+}
- PPCDBG(PPCDBG_MM, "create_valid_hpte: slot=0x%lx, hash=%d, hpte=0x%016lx 0x%016lx\n", slot, hash, lhpte.dw0.d, lhpte.dw1.d );
+static void hpte_create_valid_pSeries(unsigned long slot, unsigned long vpn,
+ unsigned long prpn, unsigned hash,
+ void * ptep, unsigned hpteflags,
+ unsigned bolted)
+{
+ /* Local copy of HPTE */
+ struct {
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } dw0;
+ /* Local copy of second doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword1 h;
+ Hpte_dword1_flags f;
+ } dw1;
+ } lhpte;
- if ( _machine == _MACH_iSeries ) {
- HvCallHpt_addValidate( slot, hash, (HPTE *)&lhpte );
- }
- else {
- HPTE * hptep = htab_data.htab + slot;
+ unsigned long avpn = vpn >> 11;
+ unsigned long arpn = physRpn_to_absRpn( prpn );
- /* Set the second dword first so that the valid bit
- * is the last thing set
- */
+ HPTE *hptep;
- hptep->dw1.dword1 = lhpte.dw1.d;
+ /* Fill in the local HPTE with absolute rpn, avpn and flags */
+ lhpte.dw1.d = 0;
+ lhpte.dw1.h.rpn = arpn;
+ lhpte.dw1.f.flags = hpteflags;
- /* Guarantee the second dword is visible before
- * the valid bit
- */
+ lhpte.dw0.d = 0;
+ lhpte.dw0.h.avpn = avpn;
+ lhpte.dw0.h.h = hash;
+ lhpte.dw0.h.bolted = bolted;
+ lhpte.dw0.h.v = 1;
- __asm__ __volatile__ ("eieio" : : : "memory");
+ /* Now fill in the actual HPTE */
+ hptep = htab_data.htab + slot;
- /* Now set the first dword including the valid bit */
- hptep->dw0.dword0 = lhpte.dw0.d;
+ /* Set the second dword first so that the valid bit
+ * is the last thing set
+ */
+
+ hptep->dw1.dword1 = lhpte.dw1.d;
- __asm__ __volatile__ ("ptesync" : : : "memory");
+ /* Guarantee the second dword is visible before
+ * the valid bit
+ */
+
+ __asm__ __volatile__ ("eieio" : : : "memory");
- }
+ /* Now set the first dword including the valid bit */
+ hptep->dw0.dword0 = lhpte.dw0.d;
+
+ __asm__ __volatile__ ("ptesync" : : : "memory");
}
/* find_linux_pte returns the address of a linux pte for a given
@@ -564,49 +632,69 @@
1 ) );
}
-static void updateHptePP( long slot, unsigned long newpp, unsigned long va )
+static void hpte_updatepp_iSeries(long slot, unsigned long newpp, unsigned long va)
{
- if ( _machine == _MACH_iSeries ) {
- HvCallHpt_setPp( slot, newpp );
- }
- else {
- /* Local copy of first doubleword of HPTE */
- union {
- unsigned long d;
- Hpte_dword0 h;
- } hpte_dw0;
-
- /* Local copy of second doubleword of HPTE */
- union {
- unsigned long d;
- Hpte_dword1 h;
- Hpte_dword1_flags f;
- } hpte_dw1;
-
- HPTE * hptep = htab_data.htab + slot;
-
- /* Turn off valid bit in HPTE */
- hpte_dw0.d = hptep->dw0.dword0;
- hpte_dw0.h.v = 0;
- hptep->dw0.dword0 = hpte_dw0.d;
-
- /* Ensure it is out of the tlb too */
- _tlbie( va );
-
- /* Insert the new pp bits into the HPTE */
- hpte_dw1.d = hptep->dw1.dword1;
- hpte_dw1.h.pp = newpp;
- hptep->dw1.dword1 = hpte_dw1.d;
+ HvCallHpt_setPp( slot, newpp );
+}
- /* Ensure it is visible before validating */
- __asm__ __volatile__ ("eieio" : : : "memory");
+static void hpte_updatepp_pSeries(long slot, unsigned long newpp, unsigned long va)
+{
+ /* Local copy of first doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword0 h;
+ } hpte_dw0;
+
+ /* Local copy of second doubleword of HPTE */
+ union {
+ unsigned long d;
+ Hpte_dword1 h;
+ Hpte_dword1_flags f;
+ } hpte_dw1;
+
+ HPTE * hptep = htab_data.htab + slot;
+
+ /* Turn off valid bit in HPTE */
+ hpte_dw0.d = hptep->dw0.dword0;
+ hpte_dw0.h.v = 0;
+ hptep->dw0.dword0 = hpte_dw0.d;
+
+ /* Ensure it is out of the tlb too */
+ _tlbie( va );
+
+ /* Insert the new pp bits into the HPTE */
+ hpte_dw1.d = hptep->dw1.dword1;
+ hpte_dw1.h.pp = newpp;
+ hptep->dw1.dword1 = hpte_dw1.d;
+
+ /* Ensure it is visible before validating */
+ __asm__ __volatile__ ("eieio" : : : "memory");
+
+ /* Turn the valid bit back on in HPTE */
+ hpte_dw0.h.v = 1;
+ hptep->dw0.dword0 = hpte_dw0.d;
- /* Turn the valid bit back on in HPTE */
- hpte_dw0.h.v = 1;
- hptep->dw0.dword0 = hpte_dw0.d;
+ __asm__ __volatile__ ("ptesync" : : : "memory");
+}
- __asm__ __volatile__ ("ptesync" : : : "memory");
- }
+/* This is called very early. */
+void htpe_init_iSeries(void)
+{
+ ppc_md.hpte_invalidate = hpte_invalidate_iSeries;
+ ppc_md.hpte_updatepp = hpte_updatepp_iSeries;
+ ppc_md.hpte_getword0 = hpte_getword0_iSeries;
+ ppc_md.hpte_selectslot = hpte_selectslot_iSeries;
+ ppc_md.hpte_create_valid = hpte_create_valid_iSeries;
+ ppc_md.hpte_find = hpte_find_iSeries;
+}
+void htpe_init_pSeries(void)
+{
+ ppc_md.hpte_invalidate = hpte_invalidate_pSeries;
+ ppc_md.hpte_updatepp = hpte_updatepp_pSeries;
+ ppc_md.hpte_getword0 = hpte_getword0_pSeries;
+ ppc_md.hpte_selectslot = hpte_selectslot_pSeries;
+ ppc_md.hpte_create_valid = hpte_create_valid_pSeries;
+ ppc_md.hpte_find = hpte_find_pSeries;
}
/* Handle a fault by adding an HPTE
@@ -640,9 +728,7 @@
* we're bolting the entire 0xC0... region.
*/
udbg_printf("Doh!!! hash_page saw a kernel address...\n");
-#if defined(CONFIG_XMON)
- xmon(0);
-#endif
+ PPCDBG_ENTER_DEBUGGER();
for(;x;x|=1);
vsid = get_kernel_vsid( ea );
@@ -671,7 +757,6 @@
}
vsid = get_vsid(mm->context, ea );
break;
- case BOLTED_REGION_ID:
default:
/* Not a valid range, send the problem up to do_page_fault */
return 1;
@@ -760,7 +845,7 @@
if ( pte_val(old_pte) & _PAGE_HPTENOIX ) {
unsigned long slot;
pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
- slot = find_hpte( vpn );
+ slot = ppc_md.hpte_find( vpn );
if ( slot != -1 ) {
if ( slot < 0 ) {
pte_val(old_pte) |= _PAGE_SECONDARY;
@@ -800,12 +885,12 @@
slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
/* If there is an HPTE for this page it is indexed by slot */
- hpte_dw0.d = get_hpte0( slot );
+ hpte_dw0.d = ppc_md.hpte_getword0( slot );
if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&
(hpte_dw0.h.v) &&
(hpte_dw0.h.h == secondary ) ){
/* HPTE matches */
- updateHptePP( slot, newpp, va );
+ ppc_md.hpte_updatepp( slot, newpp, va );
if ( !pte_same( old_pte, new_pte ) )
*ptep = new_pte;
}
@@ -822,7 +907,7 @@
*
* Find an available HPTE slot
*/
- slot = select_hpte_slot( vpn );
+ slot = ppc_md.hpte_selectslot( vpn );
/* Debug code */
if ( slot == 0x8000000000000000 ) {
@@ -865,7 +950,7 @@
hpteflags = (pte_val(new_pte) & 0x1f8) | newpp;
/* Create the HPTE */
- create_valid_hpte( slot, vpn, prpn, hash_ind, ptep, hpteflags, 0 );
+ ppc_md.hpte_create_valid( slot, vpn, prpn, hash_ind, ptep, hpteflags, 0 );
}
@@ -905,11 +990,6 @@
ptep = find_linux_pte(pgdir, ea);
pa = pte_pagenr(*ptep) << PAGE_SHIFT;
break;
- case BOLTED_REGION_ID:
- pgdir = bolted_pgd;
- ptep = find_linux_pte(pgdir, ea);
- pa = pte_pagenr(*ptep) << PAGE_SHIFT;
- break;
default:
break;
}
@@ -943,12 +1023,12 @@
/* If there is an HPTE for this page it is indexed by slot */
spin_lock_irqsave( &hash_table_lock, flags);
- hpte_dw0.d = get_hpte0( slot );
+ hpte_dw0.d = ppc_md.hpte_getword0( slot );
if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&
(hpte_dw0.h.v) &&
(hpte_dw0.h.h == secondary ) ){
/* HPTE matches */
- invalidate_hpte( slot );
+ ppc_md.hpte_invalidate( slot );
}
else {
unsigned k;
@@ -959,7 +1039,7 @@
hash = ~hash;
slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
for ( k=0; k<8; ++k ) {
- hpte_dw0.d = get_hpte0( slot+k );
+ hpte_dw0.d = ppc_md.hpte_getword0( slot+k );
if ( ( hpte_dw0.h.avpn == (vpn >> 11) ) &&
( hpte_dw0.h.v ) &&
( hpte_dw0.h.h == secondary ) ) {
@@ -1138,30 +1218,53 @@
return -EINVAL;
}
-/* round mem size up to next power of 2 -- htab size must be a power of 2 */
-unsigned long
-rounded_mem_size(unsigned long mem_size)
+static __inline__ void set_pp_bit(unsigned long pp, HPTE *addr)
{
- unsigned long rnd_mem_size;
+ unsigned long old;
+ unsigned long *p = (unsigned long *)(&(addr->dw1));
- rnd_mem_size = 1UL << (unsigned long)__ilog2(mem_size);
- if ( rnd_mem_size < mem_size )
- rnd_mem_size <<= 1;
-
- return rnd_mem_size;
+ __asm__ __volatile__(
+ "1: ldarx %0,0,%3\n\
+ rldimi %0,%2,0,62\n\
+ stdcx. %0,0,%3\n\
+ bne 1b"
+ : "=&r" (old), "=m" (*p)
+ : "r" (pp), "r" (p), "m" (*p)
+ : "cc");
}
-unsigned long
-htab_size(unsigned long mem_size)
+/*
+ * Update the page protection bits. Intended to be used to create
+ * guard pages for kernel data structures on pages which are bolted
+ * in the HPT. Assumes pages being operated on will not be stolen.
+ */
+void updateBoltedHptePP( unsigned long newpp, unsigned long ea )
{
- unsigned long offset = reloc_offset();
- struct Naca *_naca = RELOC(naca);
- unsigned long rnd_mem_size = rounded_mem_size(mem_size);
- unsigned long pteg_count = (rnd_mem_size >> (12 + 1)); /* #pages/2 */
- /* For debug, make the HTAB 1/8 as big as it normally would be. */
- if(_naca->debug_switch & PPCDBG_HTABSIZE) {
- pteg_count >>= 3;
+ unsigned long vsid,va,vpn,flags;
+ long slot;
+
+
+ vsid = get_kernel_vsid( ea );
+ va = ( vsid << 28 ) | ( ea & 0x0fffffff );
+ vpn = va >> PAGE_SHIFT;
+
+ slot = ppc_md.hpte_find( vpn );
+
+ if ( _machine == _MACH_iSeries ) {
+ HvCallHpt_setPp( slot, newpp );
+ } else {
+ HPTE * hptep = htab_data.htab + slot;
+
+ set_pp_bit(newpp , hptep );
+
+ /* Ensure it is out of the tlb too */
+ spin_lock_irqsave( &hash_table_lock, flags );
+ _tlbie( va );
+ spin_unlock_irqrestore( &hash_table_lock, flags );
+
+ /* Ensure it is visible before validating */
+ __asm__ __volatile__ ("eieio" : : : "memory");
+ __asm__ __volatile__ ("ptesync" : : : "memory");
}
- return (pteg_count << 7); /* pteg_count*128B/PTEG */
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_IoMmTable.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_IoMmTable.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.c Sat Sep 1 15:32:42 2001
@@ -34,23 +34,27 @@
#include "iSeries_IoMmTable.h"
#include "pci.h"
-void iSeries_allocateDeviceBars(struct pci_dev* PciDevPtr);
/*******************************************************************/
/* Table defines */
/* Entry size is 4 MB * 1024 Entries = 4GB. */
/*******************************************************************/
-#define iSeries_IoMmTable_Entry_Size 0x00400000
#define iSeries_IoMmTable_Size 1024
-#define iSeries_Base_Io_Memory 0xFFFFFFFF
+unsigned long iSeries_IoMmTable_Entry_Size = 0x0000000000400000;
+unsigned long iSeries_Base_Io_Memory = 0xE000000000000000;
+
+/*******************************************************************/
+/* Lookup Tables. */
+/*******************************************************************/
+struct pci_dev* iSeries_IoMmTable[iSeries_IoMmTable_Size];
+u8 iSeries_IoBarTable[iSeries_IoMmTable_Size];
/*******************************************************************/
/* Static and Global variables */
/*******************************************************************/
-struct pci_dev* iSeries_IoMmTable[iSeries_IoMmTable_Size];
-u8 iSeries_IoBarTable[iSeries_IoMmTable_Size];
-static int iSeries_CurrentIndex;
+static long iSeries_CurrentIndex;
static char* iSeriesPciIoText = "iSeries PCI I/O";
static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED;
+
/*******************************************************************/
/* iSeries_IoMmTable_Initialize */
/*******************************************************************/
@@ -59,15 +63,16 @@
/* methods. */
/*******************************************************************/
void iSeries_IoMmTable_Initialize(void) {
- int Index;
+ int Index = 0;
spin_lock(&iSeriesIoMmTableLock);
- for(Index=0;Indexresource[BarNumber];
iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber);
@@ -98,90 +102,96 @@
/*******************************************************************/
/* - Allocates the number of entries required in table base on BAR */
/* size. */
-/* - This version, allocates top down, starting at 4GB. */
+/* - This version, allocates starting at iSeries_Base_Io_Memory and*/
+/* allocate up. */
/* - The size is round up to be a multiple of entry size. */
-/* - CurrentIndex is decremented to keep track of the last entry. */
+/* - CurrentIndex is incremented to keep track of the last entry. */
/* - Builds the resource entry for allocated BARs. */
/*******************************************************************/
void iSeries_IoMmTable_AllocateEntry(struct pci_dev* PciDev, int BarNumber) {
- struct resource* BarResource = &PciDev->resource[BarNumber];
- int BarSize = BarResource->end - BarResource->start;
- unsigned long BarStartAddr;
- unsigned long BarEndAddr;
- /***************************************************************/
- /* No space to allocate, skip Allocation. */
- /***************************************************************/
- if(BarSize == 0) return; /* Quick stage exit */
-
- /***************************************************************/
- /* Allocate the table entries needed. */
- /***************************************************************/
+ struct resource* BarResource = &PciDev->resource[BarNumber];
+ long BarSize = pci_resource_len(PciDev,BarNumber);
+ /***************************************************************
+ * No space to allocate, quick exit, skip Allocation. *
+ ***************************************************************/
+ if(BarSize == 0) return;
+ //PPCDBG(PPCDBG_BUSWALK,"iSeries_IoMmTable_AllocateEntry Bar:%2d Index:0x%08X\n",BarNumber,iSeries_CurrentIndex);
+ /**************************************************************
+ * Set Resource values. *
+ ***************************************************************/
+ BarResource->name = iSeriesPciIoText;
+ BarResource->start = iSeries_IoMmTable_Entry_Size*(iSeries_CurrentIndex);
+ BarResource->start+= iSeries_Base_Io_Memory;
+ BarResource->end = BarResource->start+BarSize-1;
+ /**************************************************************
+ * Allocate the number of table entries needed. *
+ ***************************************************************/
spin_lock(&iSeriesIoMmTableLock);
- while(BarSize > 0) {
- iSeries_IoMmTable[iSeries_CurrentIndex] = PciDev;
+ while(BarSize > 0 ) {
+ iSeries_IoMmTable [iSeries_CurrentIndex] = PciDev;
iSeries_IoBarTable[iSeries_CurrentIndex] = BarNumber;
BarSize -= iSeries_IoMmTable_Entry_Size;
- --iSeries_CurrentIndex; /* Next Free entry */
+ ++iSeries_CurrentIndex;
}
spin_unlock(&iSeriesIoMmTableLock);
- BarStartAddr = iSeries_IoMmTable_Entry_Size*(iSeries_CurrentIndex+1);
- BarEndAddr = BarStartAddr + (BarResource->end - BarResource->start);
- /***************************************************************/
- /* Build Resource info */
- /***************************************************************/
- BarResource->name = iSeriesPciIoText;
- BarResource->start = (long)BarStartAddr;
- BarResource->end = (long)BarEndAddr;
-
- PPCDBG(PPCDBG_BUSWALK,"BarAloc %04X-%016LX\n",iSeries_CurrentIndex+1,BarStartAddr);
}
/*******************************************************************/
/* Translates an I/O Memory address to pci_dev* */
/*******************************************************************/
-struct pci_dev* iSeries_xlateIoMmAddress(unsigned long* IoAddress) {
- int PciDevIndex = (unsigned long)IoAddress/iSeries_IoMmTable_Entry_Size;
- struct pci_dev* PciDev = iSeries_IoMmTable[PciDevIndex];
- if(PciDev == 0) {
- printk("PCI: Invalid I/O Address: 0x%016LX\n",IoAddress);
- PCIFR("Invalid MMIO Address 0x%016LX",(unsigned long)IoAddress);
+struct pci_dev* iSeries_xlateIoMmAddress(void* IoAddress) {
+ long TableIndex = ((unsigned long)IoAddress-iSeries_Base_Io_Memory)/iSeries_IoMmTable_Entry_Size;
+ struct pci_dev* PciDev = iSeries_IoMmTable[TableIndex];
+ if(PciDev == NULL) {
+ printk("PCI: Invalid I/O Address: 0x%016lX\n",(unsigned long)IoAddress);
+ PCIFR( "Invalid MMIO Address 0x%016lX", (unsigned long)IoAddress);
}
return PciDev;
}
/************************************************************************/
/* Returns the Bar number of Address */
/************************************************************************/
-int iSeries_IoMmTable_Bar(unsigned long* IoAddress) {
- int BarIndex = (unsigned long)IoAddress/iSeries_IoMmTable_Entry_Size;
- int BarNumber = iSeries_IoBarTable[BarIndex];
- return BarNumber;
+int iSeries_IoMmTable_Bar(void* IoAddress) {
+ long TableIndex = ((unsigned long)IoAddress-iSeries_Base_Io_Memory)/iSeries_IoMmTable_Entry_Size;
+ return iSeries_IoBarTable[TableIndex];
}
/************************************************************************/
-/* Return the Bar Base Address or 0. */
-/************************************************************************/
-unsigned long* iSeries_IoMmTable_BarBase(unsigned long* IoAddress) {
- unsigned long BaseAddr = 0;
- struct pci_dev* PciDev = iSeries_xlateIoMmAddress(IoAddress);
- if(PciDev != NULL) {
- int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
- if(BarNumber != -1) {
- BaseAddr = PciDev->resource[BarNumber].start;
- }
+/* Return the Bar Base Address or NULL */
+/************************************************************************/
+void* iSeries_IoMmTable_BarBase(void* IoAddress) {
+ long TableIndex = ((unsigned long)IoAddress-iSeries_Base_Io_Memory)/iSeries_IoMmTable_Entry_Size;
+ struct pci_dev* PciDev = iSeries_IoMmTable[TableIndex];
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ if(PciDev == NULL || BarNumber == 0xFF) {
+ return NULL;
}
- return (unsigned long*)BaseAddr;
+ return (void*)(pci_resource_start(PciDev,BarNumber));
}
/************************************************************************/
/* Return the Bar offset within the Bar Space */
/* Note: Assumes that address is valid. */
/************************************************************************/
-unsigned long iSeries_IoMmTable_BarOffset(unsigned long* IoAddress) {
+unsigned long iSeries_IoMmTable_BarOffset(void* IoAddress) {
return (unsigned long)IoAddress-(unsigned long)iSeries_IoMmTable_BarBase(IoAddress);
}
-/************************************************************************/
-/* Return 0 if Address is valid I/O Address */
-/************************************************************************/
-int iSeries_Is_IoMmAddress(unsigned long* IoAddress) {
- if( iSeries_xlateIoMmAddress(IoAddress) == NULL) return 1;
- else return 0;
+/************************************************************************
+ * List the table entries out.
+ ************************************************************************/
+void iSeries_IoMmTable_Status(void) {
+ int Loop = 0;
+ struct pci_dev* PciDev = NULL;
+ int BarMinNumber = 0;
+
+ for(Loop = 0;Loop < iSeries_CurrentIndex;++Loop) {
+ if (PciDev != iSeries_IoMmTable[Loop] ) {
+ PciDev = iSeries_IoMmTable[Loop] ;
+ BarMinNumber = iSeries_IoBarTable[Loop];
+ printk("\nPCI: %3d. PciDev: 0x%016lX Bar %2d,",Loop,(unsigned long)PciDev,BarMinNumber);
+ }
+ if(BarMinNumber != iSeries_IoBarTable[Loop] ) {
+ BarMinNumber = iSeries_IoBarTable[Loop];
+ printk("%2d,",BarMinNumber);
+ }
+ }
+ printk("\nPci: %3d. Max Entries = %d\n",Loop, (int)(Loop*sizeof(void*)) );
}
-
-
+
\ No newline at end of file
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_IoMmTable.h linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.h
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_IoMmTable.h Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_IoMmTable.h Sat Sep 1 14:30:51 2001
@@ -24,9 +24,12 @@
/************************************************************************/
/* Change Activity: */
/* Created December 12, 2000 */
+/* Ported to ppc64, August 30, 2001 */
/* End Change Activity */
/************************************************************************/
+struct pci_dev;
+
/************************************************************************/
/* iSeries_IoMmTable_Initialize */
/************************************************************************/
@@ -45,7 +48,7 @@
/* - Allocates ALL pci_dev BAR's and updates the resources with the BAR */
/* value. BARS with zero length will not have the resources. The */
/* HvCallPci_getBarParms is used to get the size of the BAR space. */
-/* It calls as400_IoMmTable_AllocateEntry to allocate each entry. */
+/* It calls iSeries_IoMmTable_AllocateEntry to allocate each entry. */
/* */
/* Parameters: */
/* pci_dev = Pointer to pci_dev structure that will be mapped to pseudo */
@@ -77,23 +80,22 @@
/************************************************************************/
/* iSeries_xlateIoMmAddress */
/************************************************************************/
-/* - Translates an I/O Memory address to pci_dev that has been allocated*/
-/* the psuedo I/O Address. */
+/* - Translates an I/O Memory address to Device Node that has been the */
+/* allocated the psuedo I/O Address. */
/* */
/* Parameters: */
/* IoAddress = I/O Memory Address. */
/* */
/* Return: */
-/* A pci_dev pointer to the device mapped to the I/O address. */
+/* A pci_dev to the device mapped to the I/O address. */
/************************************************************************/
-extern struct pci_dev* iSeries_xlateIoMmAddress(unsigned long* IoAddress);
+extern struct pci_dev* iSeries_xlateIoMmAddress(void* IoAddress);
/************************************************************************/
/* Helper Methods */
/************************************************************************/
-extern int iSeries_IoMmTable_Bar(unsigned long *IoAddress);
-extern unsigned long* iSeries_IoMmTable_BarBase(unsigned long* IoAddress);
-extern unsigned long iSeries_IoMmTable_BarOffset(unsigned long* IoAddress);
-extern int iSeries_Is_IoMmAddress(unsigned long* IoAddress);
-
+extern int iSeries_IoMmTable_Bar(void* IoAddress);
+extern void* iSeries_IoMmTable_BarBase(void* IoAddress);
+extern unsigned long iSeries_IoMmTable_BarOffset(void* IoAddress);
+extern void iSeries_IoMmTable_Status(void);
#endif /* _ISERIES_IOMMTABLE_H */
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_VpdInfo.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_VpdInfo.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_VpdInfo.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_VpdInfo.c Fri Aug 24 06:41:08 2001
@@ -0,0 +1,360 @@
+/************************************************************************/
+/* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001. */
+/************************************************************************/
+/* This code gets the card location of the hardware */
+/* Copyright (C) 20yy */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the: */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, */
+/* Boston, MA 02111-1307 USA */
+/************************************************************************/
+/* Change Activity: */
+/* Created, Feb 2, 2001 */
+/* Ported to ppc64, August 20, 2001 */
+/* End Change Activity */
+/************************************************************************/
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "pci.h"
+
+/************************************************/
+/* Size of Bus VPD data */
+/************************************************/
+#define BUS_VPDSIZE 1024
+/************************************************/
+/* Bus Vpd Tags */
+/************************************************/
+#define VpdEndOfDataTag 0x78
+#define VpdEndOfAreaTag 0x79
+#define VpdIdStringTag 0x82
+#define VpdVendorAreaTag 0x84
+/************************************************/
+/* Mfg Area Tags */
+/************************************************/
+#define VpdAsmPartNumber 0x504E // "PN"
+#define VpdFruFlag 0x4647 // "FG"
+#define VpdFruLocation 0x464C // "FL"
+#define VpdFruFrameId 0x4649 // "FI"
+#define VpdFruPartNumber 0x464E // "FN"
+#define VpdFruPowerData 0x5052 // "PR"
+#define VpdFruSerial 0x534E // "SN"
+#define VpdFruType 0x4343 // "CC"
+#define VpdFruCcinExt 0x4345 // "CE"
+#define VpdFruRevision 0x5256 // "RV"
+#define VpdSlotMapFormat 0x4D46 // "MF"
+#define VpdSlotMap 0x534D // "SM"
+
+/************************************************/
+/* Structures of the areas */
+/************************************************/
+struct BusVpdAreaStruct {
+ u8 Tag;
+ u8 LowLength;
+ u8 HighLength;
+};
+typedef struct BusVpdAreaStruct BusVpdArea;
+#define BUS_ENTRY_SIZE 3
+
+struct MfgVpdAreaStruct {
+ u16 Tag;
+ u8 TagLength;
+};
+typedef struct MfgVpdAreaStruct MfgVpdArea;
+#define MFG_ENTRY_SIZE 3
+
+struct SlotMapFormatStruct {
+ u16 Tag;
+ u8 TagLength;
+ u16 Format;
+};
+
+struct FrameIdMapStruct{
+ u16 Tag;
+ u8 TagLength;
+ u8 FrameId;
+};
+typedef struct FrameIdMapStruct FrameIdMap;
+
+struct SlotMapStruct {
+ u8 AgentId;
+ u8 SecondaryAgentId;
+ u8 PhbId;
+ char CardLocation[3];
+ char Parms[8];
+ char Reserved[2];
+};
+typedef struct SlotMapStruct SlotMap;
+#define SLOT_ENTRY_SIZE 16
+
+/****************************************************************/
+/* Prototypes */
+/****************************************************************/
+static void iSeries_Parse_Vpd(BusVpdArea*, int, LocationData*);
+static void iSeries_Parse_MfgArea(MfgVpdArea*,int, LocationData*);
+static void iSeries_Parse_SlotArea(SlotMap*, int, LocationData*);
+static void iSeries_Parse_PhbId(BusVpdArea*, int, LocationData*);
+
+/****************************************************************
+ * iSeries_loc-code(struct pci_dev* PciDev) *
+ * *
+ * Gets the frame and card location of the pci_dev device. The *
+ * return is a kmalloc string. The user must free this string *
+ * when they are done. This is specifically for the device tree*
+ * *
+ * Returns: *
+ * "Frame 1, Card C10" *
+ ****************************************************************/
+char* iSeries_Location_Code(struct pci_dev* PciDev) {
+ char TempBuffer[128];
+ LocationData* LocationPtr = iSeries_GetLocationData(PciDev);
+ int LineLen = sprintf(TempBuffer," Frame%3d, Card %4s ",
+ LocationPtr->FrameId,LocationPtr->CardLocation);
+ char* RtnString = kmalloc(LineLen+7,GFP_KERNEL);
+ strcpy(RtnString,TempBuffer);
+ kfree(LocationPtr);
+ return RtnString;
+}
+/****************************************************************/
+/* */
+/* */
+/* */
+/****************************************************************/
+LocationData* iSeries_GetLocationData(struct pci_dev* PciDev) {
+ LocationData* LocationPtr = 0;
+ BusVpdArea* BusVpdPtr = 0;
+ int BusVpdLen = 0;
+ BusVpdPtr = (BusVpdArea*)kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+ BusVpdLen = HvCallPci_getBusVpd(PciDev->bus->number,REALADDR(BusVpdPtr),BUS_VPDSIZE);
+ /* printk("PCI: VpdBuffer 0x%08X \n",(int)BusVpdPtr); */
+ /***************************************************************/
+ /* Need to set Agent Id, Bus in location info before the call */
+ /***************************************************************/
+ LocationPtr = (LocationData*)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL);
+ LocationPtr->Bus = PciDev->bus->number;
+ LocationPtr->Board = 0;
+ LocationPtr->FrameId = 0;
+ iSeries_Parse_PhbId(BusVpdPtr,BusVpdLen,LocationPtr);
+ LocationPtr->Card = PCI_SLOT(PciDev->devfn);
+ strcpy(LocationPtr->CardLocation,"Cxx");
+ LocationPtr->AgentId = ISERIES_DECODE_DEVICE(PciDev->devfn);
+ LocationPtr->SecondaryAgentId = 0x10;
+ /* And for Reference only. */
+ LocationPtr->LinuxBus = PciDev->bus->number;
+ LocationPtr->LinuxDevFn = PciDev->devfn;
+ /***************************************************************/
+ /* Any data to process? */
+ /***************************************************************/
+ if(BusVpdLen > 0) {
+ iSeries_Parse_Vpd(BusVpdPtr, BUS_VPDSIZE, LocationPtr);
+ }
+ else {
+ PCIFR("No VPD Data....");
+ }
+ kfree(BusVpdPtr);
+
+ return LocationPtr;
+}
+/****************************************************************/
+/* */
+/****************************************************************/
+void iSeries_Parse_Vpd(BusVpdArea* VpdData,int VpdLen, LocationData* LocationPtr) {
+ MfgVpdArea* MfgVpdPtr = 0;
+ int BusTagLen = 0;
+ BusVpdArea* BusVpdPtr = VpdData;
+ int BusVpdLen = VpdLen;
+ /*************************************************************/
+ /* Make sure this is what I think it is */
+ /*************************************************************/
+ if(BusVpdPtr->Tag != VpdIdStringTag) { /*0x82 */
+ PCIFR("Not 0x82 start of VPD.");
+ return;
+ }
+ BusTagLen = (BusVpdPtr->HighLength*256)+BusVpdPtr->LowLength;
+ BusTagLen += BUS_ENTRY_SIZE;
+ BusVpdPtr = (BusVpdArea*)((u32)BusVpdPtr+BusTagLen);
+ BusVpdLen -= BusTagLen;
+ /*************************************************************/
+ /* Parse the Data */
+ /*************************************************************/
+ while(BusVpdLen > 0 ) {
+ BusTagLen = (BusVpdPtr->HighLength*256)+BusVpdPtr->LowLength;
+ /*********************************************************/
+ /* End of data Found */
+ /*********************************************************/
+ if(BusVpdPtr->Tag == VpdEndOfAreaTag) {
+ BusVpdLen = 0; /* Done, Make sure */
+ }
+ /*********************************************************/
+ /* Was Mfg Data Found */
+ /*********************************************************/
+ else if(BusVpdPtr->Tag == VpdVendorAreaTag) {
+ MfgVpdPtr = (MfgVpdArea*)((u32)BusVpdPtr+BUS_ENTRY_SIZE);
+ iSeries_Parse_MfgArea(MfgVpdPtr,BusTagLen,LocationPtr);
+ }
+ /********************************************************/
+ /* On to the next tag. */
+ /********************************************************/
+ if(BusVpdLen > 0) {
+ BusTagLen += BUS_ENTRY_SIZE;
+ BusVpdPtr = (BusVpdArea*)((u32)BusVpdPtr+BusTagLen);
+ BusVpdLen -= BusTagLen;
+ }
+ }
+}
+
+/*****************************************************************/
+/* Parse the Mfg Area */
+/*****************************************************************/
+void iSeries_Parse_MfgArea(MfgVpdArea* VpdDataPtr,int VpdLen, LocationData* LocationPtr) {
+ SlotMap* SlotMapPtr = 0;
+ u16 SlotMapFmt = 0;
+ int MfgTagLen = 0;
+ MfgVpdArea* MfgVpdPtr = VpdDataPtr;
+ int MfgVpdLen = VpdLen;
+
+ /*************************************************************/
+ /* Parse Mfg Data */
+ /*************************************************************/
+ while(MfgVpdLen > 0) {
+ MfgTagLen = MfgVpdPtr->TagLength;
+ if (MfgVpdPtr->Tag == VpdFruFlag) {} /* FG */
+ else if(MfgVpdPtr->Tag == VpdFruSerial) {} /* SN */
+ else if(MfgVpdPtr->Tag == VpdAsmPartNumber){} /* PN */
+ /*********************************************************/
+ /* Frame ID */
+ /*********************************************************/
+ if(MfgVpdPtr->Tag == VpdFruFrameId) { /* FI */
+ LocationPtr->FrameId = ((FrameIdMap*)MfgVpdPtr)->FrameId;
+ }
+ /*********************************************************/
+ /* Slot Map Format */
+ /*********************************************************/
+ else if(MfgVpdPtr->Tag == VpdSlotMapFormat){ /* MF */
+ SlotMapFmt = ((struct SlotMapFormatStruct*)MfgVpdPtr)->Format;
+ }
+ /*********************************************************/
+ /* Slot Labels */
+ /*********************************************************/
+ else if(MfgVpdPtr->Tag == VpdSlotMap){ /* SM */
+ if(SlotMapFmt == 0x1004) SlotMapPtr = (SlotMap*)((u32)MfgVpdPtr+MFG_ENTRY_SIZE+1);
+ else SlotMapPtr = (SlotMap*)((u32)MfgVpdPtr+MFG_ENTRY_SIZE);
+ iSeries_Parse_SlotArea(SlotMapPtr,MfgTagLen, LocationPtr);
+ }
+ /*********************************************************/
+ /* Point to the next Mfg Area */
+ /* Use defined size, sizeof give wrong answer */
+ /*********************************************************/
+ MfgTagLen += MFG_ENTRY_SIZE;
+ MfgVpdPtr = (MfgVpdArea*)( (u32)MfgVpdPtr + MfgTagLen);
+ MfgVpdLen -= MfgTagLen;
+ }
+}
+/*****************************************************************/
+/* Look for "BUS" Tag to set the PhbId. */
+/*****************************************************************/
+void iSeries_Parse_PhbId(BusVpdArea* VpdData,int VpdLen,LocationData* LocationPtr) {
+ int PhbId = 0xff; /* Not found flag */
+ char* PhbPtr = (char*)VpdData+3; /* Skip over 82 tag */
+ int DataLen = VpdLen;
+ while(DataLen > 0) {
+ if(*PhbPtr == 'B' && *(PhbPtr+1) == 'U' && *(PhbPtr+2) == 'S') {
+ if(*(PhbPtr+3) == ' ') PhbPtr += 4;/* Skip white spac*/
+ else PhbPtr += 3;
+ if (*PhbPtr == '0') PhbId = 0; /* Don't convert, */
+ else if(*PhbPtr == '1') PhbId = 1; /* Sanity check */
+ else if(*PhbPtr == '2') PhbId = 2; /* values */
+ DataLen = 0; /* Exit loop. */
+ }
+ ++PhbPtr;
+ --DataLen;
+ }
+ LocationPtr->PhbId = PhbId;
+}
+/*****************************************************************/
+/* Parse the Slot Area */
+/*****************************************************************/
+void iSeries_Parse_SlotArea(SlotMap* MapPtr,int MapLen, LocationData* LocationPtr) {
+ int SlotMapLen = MapLen;
+ SlotMap* SlotMapPtr = MapPtr;
+ /*************************************************************/
+ /* Parse Slot label until we find the one requrested */
+ /*************************************************************/
+ while(SlotMapLen > 0) {
+ if(SlotMapPtr->AgentId == LocationPtr->AgentId &&
+ SlotMapPtr->SecondaryAgentId == LocationPtr->SecondaryAgentId) {
+ /*****************************************************/
+ /* If Phb wasn't found, grab the first one found. */
+ /*****************************************************/
+ if(LocationPtr->PhbId == 0xff) LocationPtr->PhbId = SlotMapPtr->PhbId;
+ if( SlotMapPtr->PhbId == LocationPtr->PhbId ) {
+ /*****************************************************/
+ /* Found what we were looking for, extract the data. */
+ /*****************************************************/
+ memcpy(&LocationPtr->CardLocation,&SlotMapPtr->CardLocation,3);
+ LocationPtr->CardLocation[3] = 0; /* Null terminate*/
+ SlotMapLen = 0; /* We are done */
+ }
+ }
+ /*********************************************************/
+ /* Point to the next Slot */
+ /* Use defined size, sizeof may give wrong answer */
+ /*********************************************************/
+ SlotMapLen -= SLOT_ENTRY_SIZE;
+ SlotMapPtr = (SlotMap*)((u32)SlotMapPtr+SLOT_ENTRY_SIZE);
+ }
+}
+/************************************************************************/
+/* Formats the device information. */
+/* - Pass in pci_dev* pointer to the device. */
+/* - Pass in buffer to place the data. Danger here is the buffer must */
+/* be as big as the client says it is. Should be at least 128 bytes.*/
+/* Return will the length of the string data put in the buffer. */
+/* Format: */
+/* PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet */
+/* controller */
+/************************************************************************/
+int iSeries_Device_Information(struct pci_dev* PciDev,char* Buffer, int BufferSize) {
+ LocationData* LocationPtr; /* VPD Information */
+ char* BufPtr = Buffer;
+ int LineLen = 0;
+ if(BufferSize >= 128) {
+ LineLen = sprintf(BufPtr+LineLen,"PCI: Bus%3d, Device%3d, Vendor %04X ",
+ PciDev->bus->number, PCI_SLOT(PciDev->devfn),PciDev->vendor);
+
+ LocationPtr = iSeries_GetLocationData(PciDev);
+ LineLen += sprintf(BufPtr+LineLen," Frame%3d, Card %4s ",
+ LocationPtr->FrameId,LocationPtr->CardLocation);
+ kfree(LocationPtr);
+
+ if(pci_class_name(PciDev->class >> 8) == 0) {
+ LineLen += sprintf(BufPtr+LineLen,"0x%04X ",(int)(PciDev->class >> 8));
+ }
+ else {
+ LineLen += sprintf(BufPtr+LineLen,"%s",pci_class_name(PciDev->class >> 8) );
+ }
+ }
+ return LineLen;
+}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_dma.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_dma.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_dma.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_dma.c Wed Dec 31 18:00:00 1969
@@ -1,1121 +0,0 @@
-/*
- * iSeries_dma.c
- * Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
- * Dynamic DMA mapping support.
- *
- * Manages the TCE space assigned to this partition
- *
- * modeled from pci-dma.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/*#define DEBUG_TCE 1 */
-
-/*HACK HACK HACK */
-
-u8 iSeries_Get_Bus( struct pci_dev * dv )
-{
- return 0;
-}
-
-/* HACK HACK HACK */
-
-unsigned long phb_tce_table_init( void * x )
-{
- return (unsigned long)x;
-}
-
-
-struct TceTable virtBusTceTable; /* Tce table for virtual bus */
-
-struct TceTable * tceTables[256]; /* Tce tables for 256 busses
- * Bus 255 is the virtual bus
- * zero indicates no bus defined
- */
- /* allocates a contiguous range of tces (power-of-2 size) */
-static long alloc_tce_range( struct TceTable *,
- unsigned order );
- /* allocates a contiguous range of tces (power-of-2 size)
- * assumes lock already held
- */
-static long alloc_tce_range_nolock( struct TceTable *,
- unsigned order );
- /* frees a contiguous range of tces (power-of-2 size) */
-static void free_tce_range( struct TceTable *,
- long tcenum,
- unsigned order );
- /* frees a contiguous rnage of tces (power-of-2 size)
- * assumes lock already held
- */
-static void free_tce_range_nolock( struct TceTable *,
- long tcenum,
- unsigned order );
- /* allocates a range of tces and sets them to the pages */
-static dma_addr_t get_tces( struct TceTable *,
- unsigned order,
- void *page,
- unsigned numPages,
- int tceType,
- int direction );
-static void free_tces( struct TceTable *,
- dma_addr_t tce,
- unsigned order,
- unsigned numPages );
-static long test_tce_range( struct TceTable *,
- long tcenum,
- unsigned order );
-
-static unsigned fill_scatterlist_sg( struct scatterlist *sg, int nents,
- dma_addr_t dma_addr, unsigned long numTces );
-
-static unsigned long num_tces_sg( struct scatterlist *sg,
- int nents );
-
-static dma_addr_t create_tces_sg( struct TceTable *tbl,
- struct scatterlist *sg,
- int nents,
- unsigned numTces,
- int tceType,
- int direction );
-
-static unsigned __inline__ count_leading_zeros32( unsigned long x )
-{
- unsigned lz;
- asm("cntlzw %0,%1" : "=r"(lz) : "r"(x));
- return lz;
-}
-
-static void __inline__ build_tce( struct TceTable * tbl, long tcenum,
- unsigned long uaddr, int tceType, int direction )
-{
- u64 setTceRc;
- union Tce tce;
-
- tce.wholeTce = 0;
- tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT;
- /* If for virtual bus */
- if ( tceType == TCE_VB ) {
- tce.tceBits.valid = 1;
- tce.tceBits.allIo = 1;
- if ( direction != PCI_DMA_TODEVICE )
- tce.tceBits.readWrite = 1;
- }
- /* If for PCI bus */
- else {
- tce.tceBits.readWrite = 1; // Read allowed
- if ( direction != PCI_DMA_TODEVICE )
- tce.tceBits.pciWrite = 1;
- }
- setTceRc = HvCallXm_setTce( (u64)tbl->index, (u64)tcenum, tce.wholeTce );
- if ( setTceRc ) {
- printk("build_tce: HvCallXm_setTce failed, rc=%ld, index=%ld, tcenum=%0lx, tce=%016lx\n",
- setTceRc, (u64)tbl->index, (u64)tcenum, tce.wholeTce );
- }
-
-}
-
-
-
-/* Build a TceTable structure. This contains a multi-level bit map which
- * is used to manage allocation of the tce space.
- */
-
-struct TceTable * build_tce_table( struct HvTceTableManagerCB * tceTableParms,
- struct TceTable * tbl )
-{
- unsigned long bits, bytes, totalBytes;
- unsigned long numBits[NUM_TCE_LEVELS], numBytes[NUM_TCE_LEVELS];
- unsigned i, k, m;
- unsigned char * pos, * p, b;
-
- tbl->size = tceTableParms->size;
- tbl->busNumber = tceTableParms->busNumber;
- tbl->startOffset = tceTableParms->startOffset;
- tbl->index = tceTableParms->index;
- spin_lock_init( &(tbl->lock) );
-
- tbl->mlbm.maxLevel = 0;
-
- /* Compute number of bits and bytes for each level of the
- * multi-level bit map
- */
- totalBytes = 0;
- bits = tbl->size * (PAGE_SIZE / sizeof( union Tce ));
-
- for ( i=0; imlbm.level[i].map = pos;
- tbl->mlbm.maxLevel = i;
-
- if ( numBits[i] & 1 ) {
- p = pos + numBytes[i] - 1;
- m = (( numBits[i] % 8) - 1) & 7;
- *p = 0x80 >> m;
-#ifdef DEBUG_TCE
- printk("build_tce_table: level %d last bit %x\n", i, 0x80>>m );
-#endif
- }
- }
- else
- tbl->mlbm.level[i].map = 0;
- pos += numBytes[i];
- /* see the comment up above on the totalBytes calculation
- * for why we do this. */
- pos += ((numBytes[i] + 7) / 8) * 8;
-
- tbl->mlbm.level[i].numBits = numBits[i];
- tbl->mlbm.level[i].numBytes = numBytes[i];
-
- }
-
- /* For the highest level, turn on all the bits */
-
- i = tbl->mlbm.maxLevel;
- p = tbl->mlbm.level[i].map;
- m = numBits[i];
-#ifdef DEBUG_TCE
- printk("build_tce_table: highest level (%d) has all bits set\n", i);
-#endif
- for (k=0; k= 8 ) {
- /* handle full bytes */
- *p++ = 0xff;
- m -= 8;
- }
- else {
- /* handle the last partial byte */
- b = 0x80;
- *p = 0;
- while (m) {
- *p |= b;
- b >>= 1;
- --m;
- }
- }
- }
-
- return tbl;
-
-}
-
-static long alloc_tce_range( struct TceTable *tbl, unsigned order )
-{
- long retval;
- unsigned long flags;
-
- /* Lock the tce allocation bitmap */
- spin_lock_irqsave( &(tbl->lock), flags );
-
- /* Do the actual work */
- retval = alloc_tce_range_nolock( tbl, order );
-
- /* Unlock the tce allocation bitmap */
- spin_unlock_irqrestore( &(tbl->lock), flags );
-
- return retval;
-}
-
-static long alloc_tce_range_nolock( struct TceTable *tbl, unsigned order )
-{
- unsigned long numBits, numBytes;
- unsigned long i, bit, block, mask;
- long tcenum;
- u32 * map;
-
- /* If the order (power of 2 size) requested is larger than our
- * biggest, indicate failure
- */
- if ( order > tbl->mlbm.maxLevel ) {
- printk("alloc_tce_range_nolock: invalid order requested, order = %d\n", order );
- return -1;
- }
-
- numBits = tbl->mlbm.level[order].numBits;
- numBytes = tbl->mlbm.level[order].numBytes;
- map = (u32 *)(tbl->mlbm.level[order].map);
-
- /* Initialize return value to -1 (failure) */
- tcenum = -1;
-
- /* Loop through the bytes of the bitmap */
- for (i=0; i> bit);
- *map &= mask;
- /* compute the index into our tce table for
- * the first tce in the block
- */
-#ifdef DEBUG_TCE
- printk("alloc_tce_range_nolock: allocating block %ld, (byte=%ld, bit=%ld) order %d\n", block, i, bit, order );
-#endif
- tcenum = block << order;
- break;
- }
- ++map;
- }
-
-#ifdef DEBUG_TCE
- if ( tcenum == -1 ) {
- printk("alloc_tce_range_nolock: no available blocks of order = %d\n", order );
- if ( order < tbl->mlbm.maxLevel )
- printk("alloc_tce_range_nolock: trying next bigger size\n" );
- else
- printk("alloc_tce_range_nolock: maximum size reached...failing\n");
- }
-#endif
-
- /* If no block of the requested size was found, try the next
- * size bigger. If one of those is found, return the second
- * half of the block to freespace and keep the first half
- */
- if ( ( tcenum == -1 ) && ( order < tbl->mlbm.maxLevel ) ) {
- tcenum = alloc_tce_range_nolock( tbl, order+1 );
- if ( tcenum != -1 ) {
- free_tce_range_nolock( tbl, tcenum+(1<lock), flags );
-
- /* Do the actual work */
- free_tce_range_nolock( tbl, tcenum, order );
-
- /* Unlock the tce allocation bitmap */
- spin_unlock_irqrestore( &(tbl->lock), flags );
-
-}
-
-static void free_tce_range_nolock( struct TceTable *tbl, long tcenum, unsigned order )
-{
- unsigned long block;
- unsigned byte, bit, mask, b;
- unsigned char * map, * bytep;
-
- if ( order > tbl->mlbm.maxLevel ) {
- printk("free_tce_range: order too large, order = %d, tcenum = %ld\n", order, tcenum );
- return;
- }
-
- block = tcenum >> order;
- if ( tcenum != (block << order ) ) {
- printk("free_tce_range: tcenum %lx is not on appropriate boundary for order %x\n", tcenum, order );
- return;
- }
- if ( block >= tbl->mlbm.level[order].numBits ) {
- printk("free_tce_range: tcenum %lx is outside the range of this map (order %x, numBits %lx\n", tcenum, order, tbl->mlbm.level[order].numBits );
- return;
- }
-#ifdef DEBUG_TCE
- if ( test_tce_range( tbl, tcenum, order ) ) {
- printk("free_tce_range: freeing range not completely allocated.\n");
- printk("free_tce_range: TceTable %p, tcenum %lx, order %x\n", tbl, tcenum, order );
- }
-#endif
- map = tbl->mlbm.level[order].map;
- byte = block / 8;
- bit = block % 8;
- mask = 0x80 >> bit;
- bytep = map + byte;
-#ifdef DEBUG_TCE
- printk("free_tce_range_nolock: freeing block %ld (byte=%d, bit=%d) of order %d\n",block, byte, bit, order);
- if ( *bytep & mask )
- printk("free_tce_range: already free: TceTable %p, tcenum %lx, order %x\n", tbl, tcenum, order );
-#endif
- *bytep |= mask;
-
- /* If there is a higher level in the bit map than this we may be
- * able to buddy up this block with its partner.
- * If this is the highest level we can't buddy up
- * If this level has an odd number of bits and
- * we are freeing the last block we can't buddy up
- */
- if ( ( order < tbl->mlbm.maxLevel ) &&
- ( ( 0 == ( tbl->mlbm.level[order].numBits & 1 ) ) ||
- ( block < tbl->mlbm.level[order].numBits-1 ) ) ) {
-
- /* See if we can buddy up the block we just freed */
- bit &= 6; /* get to the first of the buddy bits */
- mask = 0xc0 >> bit; /* build two bit mask */
- b = *bytep & mask; /* Get the two bits */
- if ( 0 == (b ^ mask) ) { /* If both bits are on */
- /* both of the buddy blocks are free we can combine them */
- *bytep ^= mask; /* turn off the two bits */
- block = ( byte * 8 ) + bit; /* block of first of buddies */
- tcenum = block << order;
- /* free the buddied block */
-#ifdef DEBUG_TCE
- printk("free_tce_range: buddying up block %ld and block %ld\n", block, block+1);
-#endif
- free_tce_range_nolock( tbl, tcenum, order+1 );
- }
- }
-}
-
-static long test_tce_range( struct TceTable *tbl, long tcenum, unsigned order )
-{
- unsigned long block;
- unsigned byte, bit, mask, b;
- long retval, retLeft, retRight;
- unsigned char * map;
-
- map = tbl->mlbm.level[order].map;
- block = tcenum >> order;
- byte = block / 8; /* Byte within bitmap */
- bit = block % 8; /* Bit within byte */
- mask = 0x80 >> bit;
- b = (*(map+byte) & mask ); /* 0 if block is allocated, else free */
- if ( b )
- retval = 1; /* 1 == block is free */
- else
- retval = 0; /* 0 == block is allocated */
- /* Test bits at all levels below this to ensure that all agree */
-
- if (order) {
- retLeft = test_tce_range( tbl, tcenum, order-1 );
- retRight = test_tce_range( tbl, tcenum+(1<<(order-1)), order-1 );
- if ( retLeft || retRight ) {
- retval = 2;
- }
- }
-
- /* Test bits at all levels above this to ensure that all agree */
-
- return retval;
-}
-
-static dma_addr_t get_tces( struct TceTable *tbl, unsigned order, void *page, unsigned numPages, int tceType, int direction )
-{
- long tcenum;
- unsigned long uaddr;
- unsigned i;
- dma_addr_t retTce = NO_TCE;
-
- uaddr = (unsigned long)page & PAGE_MASK;
-
- /* Allocate a range of tces */
- tcenum = alloc_tce_range( tbl, order );
- if ( tcenum != -1 ) {
- /* We got the tces we wanted */
- tcenum += tbl->startOffset; /* Offset into real TCE table */
- retTce = tcenum << PAGE_SHIFT; /* Set the return dma address */
- /* Setup a tce for each page */
- for (i=0; isize * (PAGE_SIZE / sizeof(union Tce))) - 1;
-
- tcenum = dma_addr >> PAGE_SHIFT;
- tcenum -= tbl->startOffset;
-
- if ( tcenum > maxTcenum ) {
- printk("free_tces: tcenum > maxTcenum, tcenum = %ld, maxTcenum = %ld\n",
- tcenum, maxTcenum );
- printk("free_tces: TCE Table at %16lx\n", (unsigned long)tbl );
- printk("free_tces: bus# %lu\n", (unsigned long)tbl->busNumber );
- printk("free_tces: size %lu\n", (unsigned long)tbl->size );
- printk("free_tces: startOff %lu\n", (unsigned long)tbl->startOffset );
- printk("free_tces: index %lu\n", (unsigned long)tbl->index );
- return;
- }
-
- freeTce = tcenum;
-
- for (i=0; iindex, (u64)tcenum, tce.wholeTce );
- if ( setTceRc ) {
- printk("free_tces: HvCallXm_setTce failed, rc=%ld, index=%ld, tcenum=%0lx, tce=%016lx\n",
- setTceRc, (u64)tbl->index, (u64)tcenum, tce.wholeTce );
- }
-
- ++tcenum;
- }
-
- free_tce_range( tbl, freeTce, order );
-
-}
-
-void __init create_virtual_bus_tce_table(void)
-{
- struct TceTable * t;
- struct HvTceTableManagerCB virtBusTceTableParms;
- u64 absParmsPtr;
-
- virtBusTceTableParms.busNumber = 255; /* Bus 255 is the virtual bus */
- virtBusTceTableParms.virtualBusFlag = 0xff; /* Ask for virtual bus */
-
- absParmsPtr = virt_to_absolute( (u64)&virtBusTceTableParms );
- HvCallXm_getTceTableParms( absParmsPtr );
-
- t = build_tce_table( &virtBusTceTableParms, &virtBusTceTable );
- if ( t ) {
- tceTables[255] = t;
- printk("Virtual Bus TCE table built successfully.\n");
- printk(" TCE table size = %ld entries\n",
- (unsigned long)t->size*(PAGE_SIZE/sizeof(union Tce)) );
- printk(" TCE table token = %d\n",
- (unsigned)t->index );
- printk(" TCE table start entry = 0x%lx\n",
- (unsigned long)t->startOffset );
- }
- else
- printk("Virtual Bus TCE table failed.\n");
-}
-
-void __init create_pci_bus_tce_table( unsigned busNumber )
-{
- struct TceTable * t;
- struct TceTable * newTceTable;
- struct HvTceTableManagerCB pciBusTceTableParms;
- u64 absParmsPtr;
- unsigned i;
-
- if ( busNumber > 254 ) {
- printk("PCI Bus TCE table failed.\n");
- printk(" Invalid bus number %u\n", busNumber );
- return;
- }
-
- newTceTable = kmalloc( sizeof(struct TceTable), GFP_KERNEL );
-
- pciBusTceTableParms.busNumber = busNumber;
- pciBusTceTableParms.virtualBusFlag = 0;
-
- absParmsPtr = virt_to_absolute( (u64)&pciBusTceTableParms );
- HvCallXm_getTceTableParms( absParmsPtr );
-
- /* Determine if the table identified by the index and startOffset
- * returned by the hypervisor for this bus has already been created.
- */
-
- for ( i=0; i<255; ++i ) {
- t = tceTables[i];
- if ( t ) {
- if ( ( t->index == pciBusTceTableParms.index ) &&
- ( t->startOffset == pciBusTceTableParms.startOffset ) ) {
- if ( t->size != pciBusTceTableParms.size )
- printk("PCI Bus %d Shares a TCE table with Bus %d, but sizes differ\n", busNumber, i );
- else
- printk("PCI Bus %d Shares a TCE table with Bus %d\n", busNumber, i );
- tceTables[busNumber] = t;
- break;
- }
- }
- }
-
- if ( ! tceTables[busNumber] ) {
- t = build_tce_table( &pciBusTceTableParms, newTceTable );
- if ( t ) {
- tceTables[busNumber] = t;
- printk("PCI Bus TCE table built successfully.\n");
- printk(" TCE table size = %ld entries\n",
- (unsigned long)t->size*(PAGE_SIZE/sizeof(union Tce)) );
- printk(" TCE table token = %d\n",
- (unsigned)t->index );
- printk(" TCE table start entry = 0x%lx\n",
- (unsigned long)t->startOffset );
- }
- else {
- kfree( newTceTable );
- printk("PCI Bus TCE table failed.\n");
- }
- }
-}
-
-
-/* Allocates a contiguous real buffer and creates TCEs over it.
- * Returns the virtual address of the buffer and sets dma_handle
- * to the dma address (tce) of the first page.
- */
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
-{
- struct TceTable * tbl;
- void *ret = NULL;
- unsigned order, nPages, bus;
- dma_addr_t tce;
- int tceType;
-
- size = PAGE_ALIGN(size);
- order = get_order(size);
- nPages = 1 << order;
-
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL ) {
- bus = 255;
- tceType = TCE_VB;
- }
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = ISERIES_GET_BUS( hwdev );
- tceType = TCE_PCI;
-#else
- BUG();
- return NULL;
-#endif /* CONFIG_PCI */
- }
-
- tbl = tceTables[bus];
- if ( tbl ) {
- /* Alloc enough pages (and possibly more) */
- ret = (void *)__get_free_pages( GFP_ATOMIC, order );
- if ( ret ) {
- /* Page allocation succeeded */
- memset(ret, 0, nPages << PAGE_SHIFT);
- /* Set up tces to cover the allocated range */
- tce = get_tces( tbl, order, ret, nPages, tceType,
- PCI_DMA_BIDIRECTIONAL );
- if ( tce == NO_TCE ) {
-/*#ifdef DEBUG_TCE */
- printk("pci_alloc_consistent: get_tces failed\n" );
-/*#endif */
- free_pages( (unsigned long)ret, order );
- ret = NULL;
- }
- else
- {
- *dma_handle = tce;
- }
- }
-/*#ifdef DEBUG_TCE */
- else
- printk("pci_alloc_consistent: __get_free_pages failed for order = %d\n", order);
-/*#endif*/
- }
-
- return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- struct TceTable * tbl;
- unsigned order, nPages, bus;
-
- size = PAGE_ALIGN(size);
- order = get_order(size);
- nPages = 1 << order;
-
- if ( order > 10 )
- printk("pci_free_consistent: order=%d, size=%ld, nPages=%d, dma_handle=%016lx, vaddr=%016lx\n",
- order, size, nPages, (unsigned long)dma_handle, (unsigned long)vaddr );
-
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL )
- bus = 255;
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = ISERIES_GET_BUS( hwdev );
-#else
- BUG();
- return;
-#endif /* CONFIG_PCI */
- }
-
- if ( bus > 255 ) {
- printk("pci_free_consistent: invalid bus # %d\n", bus );
- printk("pci_free_consistent: hwdev = %08lx\n", (unsigned long)hwdev );
- }
-
- tbl = tceTables[bus];
-
- if ( tbl ) {
- free_tces( tbl, dma_handle, order, nPages );
- free_pages( (unsigned long)vaddr, order );
- }
-}
-
-/* Creates TCEs for a user provided buffer. The user buffer must be
- * contiguous real kernel storage (not vmalloc). The address of the buffer
- * passed here is the kernel (virtual) address of the buffer. The buffer
- * need not be page aligned, the dma_addr_t returned will point to the same
- * byte within the page as vaddr.
- */
-dma_addr_t pci_map_single( struct pci_dev *hwdev, void *vaddr, size_t size, int direction )
-{
- struct TceTable * tbl;
- dma_addr_t dma_handle;
- unsigned long uaddr;
- unsigned order, nPages, bus;
- int tceType;
-
- if ( direction == PCI_DMA_NONE )
- BUG();
-
- dma_handle = NO_TCE;
-
- uaddr = (unsigned long)vaddr;
- nPages = PAGE_ALIGN( uaddr + size ) - ( uaddr & PAGE_MASK );
- order = get_order( nPages & PAGE_MASK );
- nPages >>= PAGE_SHIFT;
-
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL ) {
- bus = 255;
- tceType = TCE_VB;
- }
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = ISERIES_GET_BUS( hwdev );
- tceType = TCE_PCI;
-#else
- BUG();
- return NO_TCE;
-#endif /* CONFIG_PCI */
-
- }
-
- tbl = tceTables[bus];
-
- if ( tbl ) {
- dma_handle = get_tces( tbl, order, vaddr, nPages, tceType,
- direction );
- dma_handle |= ( uaddr & ~PAGE_MASK );
- }
-
- return dma_handle;
-}
-
-void pci_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction )
-{
- struct TceTable * tbl;
- unsigned order, nPages, bus;
-
- if ( direction == PCI_DMA_NONE )
- BUG();
-
- nPages = PAGE_ALIGN( dma_handle + size ) - ( dma_handle & PAGE_MASK );
- order = get_order( nPages & PAGE_MASK );
- nPages >>= PAGE_SHIFT;
-
- if ( order > 10 )
- printk("pci_unmap_single: order=%d, size=%ld, nPages=%d, dma_handle=%016lx\n",
- order, size, nPages, (unsigned long)dma_handle );
-
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL )
- bus = 255;
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = ISERIES_GET_BUS( hwdev );
-#else
- BUG();
- return;
-#endif /* CONFIG_PCI */
- }
-
- if ( bus > 255 ) {
- printk("pci_unmap_single: invalid bus # %d\n", bus );
- printk("pci_unmap_single: hwdev = %08lx\n", (unsigned long)hwdev );
- }
-
- tbl = tceTables[bus];
-
- if ( tbl )
- free_tces( tbl, dma_handle, order, nPages );
-
-}
-
-/* Figure out how many TCEs are actually going to be required
- * to map this scatterlist. This code is not optimal. It
- * takes into account the case where entry n ends in the same
- * page in which entry n+1 starts. It does not handle the
- * general case of entry n ending in the same page in which
- * entry m starts.
- */
-static unsigned long num_tces_sg( struct scatterlist *sg, int nents )
-{
- unsigned long nTces, numPages, startPage, endPage, prevEndPage;
- unsigned i;
-
- prevEndPage = 0;
- nTces = 0;
-
- for (i=0; iaddress >> PAGE_SHIFT;
- endPage = ((unsigned long)sg->address + sg->length - 1) >> PAGE_SHIFT;
- numPages = endPage - startPage + 1;
- /* Simple optimization: if the previous entry ended
- * in the same page in which this entry starts
- * then we can reduce the required pages by one.
- * This matches assumptions in fill_scatterlist_sg and
- * create_tces_sg
- */
- if ( startPage == prevEndPage )
- --numPages;
- nTces += numPages;
- prevEndPage = endPage;
- sg++;
- }
- return nTces;
-}
-
-/* Fill in the dma data in the scatterlist
- * return the number of dma sg entries created
- */
-static unsigned fill_scatterlist_sg( struct scatterlist *sg, int nents,
- dma_addr_t dma_addr , unsigned long numTces)
-{
- struct scatterlist *dma_sg;
- u32 cur_start_dma;
- unsigned long cur_len_dma, cur_end_virt, uaddr;
- unsigned num_dma_ents;
-
- dma_sg = sg;
- num_dma_ents = 1;
-
- /* Process the first sg entry */
- cur_start_dma = dma_addr + ((unsigned long)sg->address & (~PAGE_MASK));
- cur_len_dma = sg->length;
- /* cur_end_virt holds the address of the byte immediately after the
- * end of the current buffer.
- */
- cur_end_virt = (unsigned long)sg->address + cur_len_dma;
- /* Later code assumes that unused sg->dma_address and sg->dma_length
- * fields will be zero. Other archs seem to assume that the user
- * (device driver) guarantees that...I don't want to depend on that
- */
- sg->dma_address = sg->dma_length = 0;
-
- /* Process the rest of the sg entries */
- while (--nents) {
- ++sg;
- /* Clear possibly unused fields. Note: sg >= dma_sg so
- * this can't be clearing a field we've already set
- */
- sg->dma_address = sg->dma_length = 0;
-
- /* Check if it is possible to make this next entry
- * contiguous (in dma space) with the previous entry.
- */
-
- /* The entries can be contiguous in dma space if
- * the previous entry ends immediately before the
- * start of the current entry (in virtual space)
- * or if the previous entry ends at a page boundary
- * and the current entry starts at a page boundary.
- */
- uaddr = (unsigned long)sg->address;
- if ( ( uaddr != cur_end_virt ) &&
- ( ( ( uaddr | cur_end_virt ) & (~PAGE_MASK) ) ||
- ( ( uaddr & PAGE_MASK ) == ( ( cur_end_virt-1 ) & PAGE_MASK ) ) ) ) {
- /* This entry can not be contiguous in dma space.
- * save the previous dma entry and start a new one
- */
- dma_sg->dma_address = cur_start_dma;
- dma_sg->dma_length = cur_len_dma;
-
- ++dma_sg;
- ++num_dma_ents;
-
- cur_start_dma += cur_len_dma-1;
- /* If the previous entry ends and this entry starts
- * in the same page then they share a tce. In that
- * case don't bump cur_start_dma to the next page
- * in dma space. This matches assumptions made in
- * num_tces_sg and create_tces_sg.
- */
- if ((uaddr & PAGE_MASK) == ((cur_end_virt-1) & PAGE_MASK))
- cur_start_dma &= PAGE_MASK;
- else
- cur_start_dma = PAGE_ALIGN(cur_start_dma+1);
- cur_start_dma += ( uaddr & (~PAGE_MASK) );
- cur_len_dma = 0;
- }
- /* Accumulate the length of this entry for the next
- * dma entry
- */
- cur_len_dma += sg->length;
- cur_end_virt = uaddr + sg->length;
- }
- /* Fill in the last dma entry */
- dma_sg->dma_address = cur_start_dma;
- dma_sg->dma_length = cur_len_dma;
-
- if ((((cur_start_dma +cur_len_dma - 1)>> PAGE_SHIFT) - (dma_addr >> PAGE_SHIFT) + 1) != numTces)
- {
- printk("fill_scatterlist_sg: numTces %ld, used tces %d\n",
- numTces,
- (unsigned)(((cur_start_dma + cur_len_dma - 1) >> PAGE_SHIFT) - (dma_addr >> PAGE_SHIFT) + 1));
- }
-
-
- return num_dma_ents;
-}
-
-/* Call the hypervisor to create the TCE entries.
- * return the number of TCEs created
- */
-static dma_addr_t create_tces_sg( struct TceTable *tbl, struct scatterlist *sg,
- int nents, unsigned numTces, int tceType, int direction )
-{
- unsigned order, i, j;
- unsigned long startPage, endPage, prevEndPage, numPages, uaddr;
- long tcenum, starttcenum;
- dma_addr_t dmaAddr;
-
- dmaAddr = NO_TCE;
-
- order = get_order( numTces << PAGE_SHIFT );
- /* allocate a block of tces */
- tcenum = alloc_tce_range( tbl, order );
- if ( tcenum != -1 ) {
- tcenum += tbl->startOffset;
- starttcenum = tcenum;
- dmaAddr = tcenum << PAGE_SHIFT;
- prevEndPage = 0;
- for (j=0; jaddress >> PAGE_SHIFT;
- endPage = ((unsigned long)sg->address + sg->length - 1) >> PAGE_SHIFT;
- numPages = endPage - startPage + 1;
-
- uaddr = (unsigned long)sg->address;
-
- /* If the previous entry ended in the same page that
- * the current page starts then they share that
- * tce and we reduce the number of tces we need
- * by one. This matches assumptions made in
- * num_tces_sg and fill_scatterlist_sg
- */
- if ( startPage == prevEndPage ) {
- --numPages;
- uaddr += PAGE_SIZE;
- }
-
- for (i=0; idma_address = pci_map_single( hwdev, sg->address,
- sg->length, direction );
- sg->dma_length = sg->length;
- return 1;
- }
-
- if ( direction == PCI_DMA_NONE )
- BUG();
-
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL ) {
- bus = 255;
- tceType = TCE_VB;
- }
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = ISERIES_GET_BUS( hwdev );
- tceType = TCE_PCI;
-#else
- BUG();
- return 0;
-#endif /* CONFIG_PCI */
- }
-
- tbl = tceTables[bus];
-
- if ( tbl ) {
- /* Compute the number of tces required */
- numTces = num_tces_sg( sg, nents );
- /* Create the tces and get the dma address */
- dma_handle = create_tces_sg( tbl, sg, nents, numTces,
- tceType, direction );
-
- /* Fill in the dma scatterlist */
- num_dma = fill_scatterlist_sg( sg, nents, dma_handle, numTces );
- }
-
- return num_dma;
-}
-
-void pci_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int direction )
-{
- struct TceTable * tbl;
- unsigned order, numTces, bus, i;
- dma_addr_t dma_end_page, dma_start_page;
-
- if ( direction == PCI_DMA_NONE )
- BUG();
-
- dma_start_page = sg->dma_address & PAGE_MASK;
- for ( i=nelms; i>0; --i ) {
- unsigned k = i - 1;
- if ( sg[k].dma_length ) {
- dma_end_page = ( sg[k].dma_address +
- sg[k].dma_length - 1 ) & PAGE_MASK;
- break;
- }
- }
-
- numTces = ((dma_end_page - dma_start_page ) >> PAGE_SHIFT) + 1;
- order = get_order( numTces << PAGE_SHIFT );
-
- if ( order > 10 )
- printk("pci_unmap_sg: order=%d, numTces=%d, nelms=%d, dma_start_page=%016lx, dma_end_page=%016lx\n",
- order, numTces, nelms, (unsigned long)dma_start_page, (unsigned long)dma_end_page );
-
-
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL )
- bus = 255;
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = ISERIES_GET_BUS( hwdev );
-#else
- BUG();
- return;
-#endif /* CONFIG_PCI */
- }
-
- if ( bus > 255 ) {
- printk("pci_unmap_sg: invalid bus # %d\n", bus );
- printk("pci_unmap_sg: hwdev = %08lx\n", (unsigned long)hwdev );
- }
-
-
- tbl = tceTables[bus];
-
- if ( tbl )
- free_tces( tbl, dma_start_page, order, numTces );
-
-}
-
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_irq.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_irq.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_irq.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_irq.c Fri Aug 24 17:23:13 2001
@@ -0,0 +1,256 @@
+/************************************************************************/
+/* This module supports the iSeries PCI bus interrupt handling */
+/* Copyright (C) 20yy */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the: */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, */
+/* Boston, MA 02111-1307 USA */
+/************************************************************************/
+/* Change Activity: */
+/* Created, December 13, 2000 by Wayne Holm */
+/* End Change Activity */
+/************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+//#include
+
+#include
+#include
+#include
+//#include
+
+
+hw_irq_controller iSeries_IRQ_handler = {
+ "iSeries irq controller",
+ iSeries_startup_IRQ, /* startup */
+ iSeries_shutdown_IRQ, /* shutdown */
+ iSeries_enable_IRQ, /* enable */
+ iSeries_disable_IRQ, /* disable */
+ NULL, /* ack */
+ iSeries_end_IRQ, /* end */
+ NULL /* set_affinity */
+};
+
+
+struct iSeries_irqEntry {
+ u32 dsa;
+ struct iSeries_irqEntry* next;
+};
+
+struct iSeries_irqAnchor {
+ u8 valid : 1;
+ u8 reserved : 7;
+ u16 entryCount;
+ struct iSeries_irqEntry* head;
+};
+
+struct iSeries_irqAnchor iSeries_irqMap[NR_IRQS];
+
+void iSeries_init_irqMap(int irq);
+
+/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */
+void __init iSeries_init_IRQ(void)
+{
+
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].handler = &iSeries_IRQ_handler;
+ irq_desc[i].status = 0;
+ irq_desc[i].status |= IRQ_DISABLED;
+ irq_desc[i].depth = 1;
+ iSeries_init_irqMap(i);
+ }
+
+ /* Register PCI event handler and open an event path */
+ XmPciLpEvent_init();
+
+ return;
+}
+
+/* Called by iSeries_init_IRQ */
+void __init iSeries_init_irqMap(int irq) {
+ /* Prevent IRQs 0 and 255 from being used. IRQ 0 appears in
+ uninitialized devices. IRQ 255 appears in the PCI interrupt
+ line register if a PCI error occurs */
+ iSeries_irqMap[irq].valid = (irq == 0 || irq == 255)? 0 : 1;
+ iSeries_irqMap[irq].entryCount = 0;
+ iSeries_irqMap[irq].head = NULL;
+}
+
+/* This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot */
+int __init iSeries_allocate_IRQ(HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) {
+
+ u8 idsel = (deviceId >> 4);
+ u8 function = deviceId & 0x0F;
+ int irq = ((((busNumber-1)*16 + (idsel-1)*8 + function)*9/8) % 254) + 1;
+ return irq;
+}
+
+/* This is called out of iSeries_scan_slot to assign the EADS slot to its IRQ number */
+int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) {
+
+ int rc;
+ u32 dsa = (busNumber << 16) | (subBusNumber << 8) | deviceId;
+ struct iSeries_irqEntry* newEntry;
+ unsigned long flags;
+
+ if (irq < 0 || irq >= NR_IRQS)
+ return -1;
+
+ newEntry = kmalloc(sizeof(*newEntry), GFP_KERNEL);
+ if (newEntry == NULL)
+ return -ENOMEM;
+ newEntry->dsa = dsa;
+ newEntry->next = NULL;
+
+ /* Probably not necessary to lock the irq since allocation is only
+ done during buswalk, but it should not hurt anything except a little
+ performance */
+ spin_lock_irqsave(&irq_desc[irq].lock, flags);
+
+ if (iSeries_irqMap[irq].valid) {
+ /* Push the new element onto the irq stack */
+ newEntry->next = iSeries_irqMap[irq].head;
+ iSeries_irqMap[irq].head = newEntry;
+ ++iSeries_irqMap[irq].entryCount;
+ rc = 0;
+ }
+ else
+ rc = -1;
+
+ spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+
+ if (rc != 0 && newEntry)
+ kfree(newEntry);
+
+ return rc;
+
+}
+
+
+/* This is called by iSeries_activate_IRQs */
+unsigned int iSeries_startup_IRQ(unsigned int irq) {
+ struct iSeries_irqEntry* entry;
+ u32 bus, subBus, deviceId, function, mask;
+
+ /* irq should be locked by the caller */
+
+ for(entry=iSeries_irqMap[irq].head; entry!=NULL; entry=entry->next) {
+ bus = (entry->dsa >> 16) & 0xFFFF;
+ subBus = (entry->dsa >> 8) & 0xFF;
+ deviceId = entry->dsa & 0xFF;
+ function = deviceId & 0x0F;
+ /* Link the IRQ number to the bridge */
+ HvCallXm_connectBusUnit(bus, subBus, deviceId, irq);
+ /* Unmask bridge interrupts in the FISR */
+ mask = 0x01010000 << function;
+ HvCallPci_unmaskFisr(bus, subBus, deviceId, mask);
+ }
+
+ return 0;
+}
+
+/* This is called out of iSeries_fixup to
+ activate interrupt generation for usable slots */
+void __init iSeries_activate_IRQs() {
+ int irq;
+ unsigned long flags;
+
+ for (irq=0; irq < NR_IRQS; irq++) {
+ spin_lock_irqsave(&irq_desc[irq].lock, flags);
+ irq_desc[irq].handler->startup(irq);
+ spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+ }
+
+}
+
+/* this is not called anywhere currently */
+void iSeries_shutdown_IRQ(unsigned int irq) {
+ struct iSeries_irqEntry* entry;
+ u32 bus, subBus, deviceId, function, mask;
+
+ /* irq should be locked by the caller */
+
+ for(entry=iSeries_irqMap[irq].head; entry; entry=entry->next) {
+ bus = (entry->dsa >> 16) & 0xFFFF;
+ subBus = (entry->dsa >> 8) & 0xFF;
+ deviceId = entry->dsa & 0xFF;
+ function = deviceId & 0x0F;
+ /* Invalidate the IRQ number in the bridge */
+ HvCallXm_connectBusUnit(bus, subBus, deviceId, 0);
+ /* Mask bridge interrupts in the FISR */
+ mask = 0x01010000 << function;
+ HvCallPci_maskFisr(bus, subBus, deviceId, mask);
+ }
+
+}
+
+
+/* This will be called by device drivers (via disable_IRQ to disable
+ INTA in the bridge interrupt status register */
+void iSeries_disable_IRQ(unsigned int irq) {
+ struct iSeries_irqEntry* entry;
+ u32 bus, subBus, deviceId, mask;
+
+ /* The IRQ has already been locked by the caller */
+
+ for(entry=iSeries_irqMap[irq].head; entry; entry=entry->next) {
+ bus = (entry->dsa >> 16) & 0xFFFF;
+ subBus = (entry->dsa >> 8) & 0xFF;
+ deviceId = entry->dsa & 0xFF;
+ /* Mask secondary INTA */
+ mask = 0x80000000;
+ HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
+ }
+}
+
+/* This will be called by device drivers (via enable_IRQ to enable
+ INTA in the bridge interrupt status register */
+void iSeries_enable_IRQ(unsigned int irq) {
+ struct iSeries_irqEntry* entry;
+ u32 bus, subBus, deviceId, mask;
+
+ /* The IRQ has already been locked by the caller */
+
+ for(entry=iSeries_irqMap[irq].head; entry; entry=entry->next) {
+ bus = (entry->dsa >> 16) & 0xFFFF;
+ subBus = (entry->dsa >> 8) & 0xFF;
+ deviceId = entry->dsa & 0xFF;
+ /* Unmask secondary INTA */
+ mask = 0x80000000;
+ HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
+ }
+}
+
+/* Need to define this so ppc_irq_dispatch_handler will NOT call
+ enable_IRQ at the end of interrupt handling. However, this
+ does nothing because there is not enough information provided
+ to do the EOI HvCall. This is done by XmPciLpEvent.c */
+void iSeries_end_IRQ(unsigned int irq) {
+}
+
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_pci.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_pci.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_pci.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_pci.c Mon Sep 10 11:24:50 2001
@@ -27,58 +27,47 @@
#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
#include
+#include
#include
#include
+#include
+#include "iSeries_IoMmTable.h"
#include "pci.h"
extern struct pci_controller* hose_head;
extern struct pci_controller** hose_tail;
+extern int global_phb_number;
+extern int panic_timeout;
+
extern struct Naca *naca;
extern struct device_node *allnodes;
extern unsigned long phb_tce_table_init(struct pci_controller *phb);
+extern unsigned long iSeries_Base_Io_Memory;
extern struct pci_ops iSeries_pci_ops;
extern struct flightRecorder* PciFr;
int PciTraceFlag = 0;
-
-struct pci_dev;
-
-struct i_device_node {
- struct list_head iDevice_Chain;
- char* Name;
- char* Type;
- struct pci_dev* PciDev;
- int BusNumber;
- int SubBus;
- int ReturnCode;
- int DevFn;
-};
-
-LIST_HEAD(iDevice_List);
+extern void iSeries_MmIoTest(void);
/*******************************************************************
* Forward declares of prototypes.
@@ -91,57 +80,168 @@
void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb);
void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, HvSubBusNumber SubBus, int MaxAgents);
+void list_device_nodes(void);
+
+
+struct pci_dev;
+
+/* struct DsaAddr (64-bits total)
+ * u16 busNumber; 48
+ * u8 subBusNumber; 40
+ * u8 deviceId; 32
+ * u8 barNumber; 24
+ * u8 reserved[3];
+ */
+
+struct iSeries_Device_Node {
+ struct list_head Device_List; /* Must be first to allow cast to work. */
+ struct pci_dev* PciDev;
+ char* Name;
+ char* Type;
+ u64 DsaAddr;
+ int BusNumber;
+ int SubBus;
+ int AgentId;
+ int DevFn;
+ int Irq;
+ int ReturnCode;
+ int IoRetry;
+ int Flags;
+ u16 Vendor;
+ char* Location;
+ int DeviceNumber;
+};
+
+LIST_HEAD(Global_Device_List);
+
+int DeviceCount = 0;
/**********************************************************************************
+ * Dump the iSeries Temp Device Node
+ *<4>buswalk [swapper : - DeviceNode: 0xC000000000634300
+ *<4>00. Device Node = 0xC000000000634300
+ *<4> - PciDev = 0x0000000000000000
+ *<4> - tDevice = 0x 17:01.00 0x1022 00
+ *<4> 4. Device Node = 0xC000000000634480
+ *<4> - PciDev = 0x0000000000000000
+ *<4> - Device = 0x 18:38.16 Irq:0xA7 Vendor:0x1014 Flags:0x00
+ *<4> - Devfn = 0xB0: 22.18
+ **********************************************************************************/
+void dumpDevice_Node(struct iSeries_Device_Node* DeviceNode) {
+ udbg_printf("%3d. Device Node = 0x%016LX\n",DeviceNode->DeviceNumber, DeviceNode);
+ udbg_printf(" - PciDev = 0x%016LX\n",DeviceNode->PciDev);
+ udbg_printf(" - Device = 0x%4X:%02X.%02X (0x%02X)\n",
+ DeviceNode->BusNumber,
+ DeviceNode->SubBus,
+ DeviceNode->AgentId, DeviceNode->DevFn);
+ udbg_printf(" = Irq:0x%02X Vendor:0x%04X Flags:0x%02X\n",
+ DeviceNode->Irq,
+ DeviceNode->Vendor,
+ DeviceNode->Flags );
+}
+/**********************************************************************************
+ * Walk down the device node chain
+ **********************************************************************************/
+void list_device_nodes(void) {
+ struct list_head* Device_Node_Ptr = Global_Device_List.next;
+ while(Device_Node_Ptr != &Global_Device_List) {
+ dumpDevice_Node( (struct iSeries_Device_Node*)Device_Node_Ptr );
+ Device_Node_Ptr = Device_Node_Ptr->next;
+ }
+}
+
+
+/***********************************************************************
+ * build_device_node(u16 Bus, int SubBus, u8 DevFn)
*
- *
+ ***********************************************************************/
+struct iSeries_Device_Node* build_device_node(HvBusNumber Bus, HvSubBusNumber SubBus, int AgentId) {
+ struct iSeries_Device_Node* DeviceNode;
+
+ PPCDBG(PPCDBG_BUSWALK,"- "__FUNCTION__" 0x%02X.%02X.%02X\n",Bus,SubBus,AgentId);
+
+ DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
+ if(DeviceNode == NULL) return NULL;
+
+ memset(DeviceNode,0,sizeof(struct iSeries_Device_Node) );
+ list_add_tail(&DeviceNode->Device_List,&Global_Device_List);
+ DeviceNode->DsaAddr = ((u64)Bus<<48)+((u64)SubBus<<40)+((u64)0x10<<32);
+ DeviceNode->BusNumber = Bus;
+ DeviceNode->SubBus = SubBus;
+ DeviceNode->AgentId = AgentId;
+ DeviceNode->DevFn = AgentId<<3;
+ DeviceNode->DeviceNumber = DeviceCount;
+ DeviceNode->IoRetry = 0;
+ return DeviceNode;
+}
+
+
+/**********************************************************************************
+ * Look down the chain to find the matching Device Device
**********************************************************************************/
-#define ISERIES_PCI_READ_OP(size, call, type) \
-/***********************************************************************************/ \
-int iSeries_pci_read_config_##size(struct pci_dev* PciDev, int PciOffset, type ReadValue) { \
- struct i_device_node* DeviceNode = PciDev->sysdata; \
- if(DeviceNode->BusNumber == 0xFF) DeviceNode->ReturnCode = 0x301; return DeviceNode->ReturnCode; \
- DeviceNode->ReturnCode = HvCallPci_config##call(DeviceNode->BusNumber, DeviceNode->SubBus, \
- DeviceNode->DevFn, PciOffset, ReadValue); \
- if(DeviceNode->ReturnCode != 0 ) { \
- PCIFR("RC##size: %02X,%02X,%02X,%04X Rtn: %04X", \
- DeviceNode->BusNumber, DeviceNode->SubBus, DeviceNode->DevFn, PciOffset,DeviceNode->ReturnCode); \
- } \
- return DeviceNode->ReturnCode; \
-}
-/***********************************************************************************/ \
-#define ISERIES_PCI_WRITE_OP(size, call, type) \
-/***********************************************************************************/ \
-int iSeries_pci_write_config_##size(struct pci_dev* PciDev, int PciOffset, type WriteValue) { \
- struct i_device_node* DeviceNode = PciDev->sysdata; \
- DeviceNode->ReturnCode = HvCallPci_config##call(DeviceNode->BusNumber, DeviceNode->SubBus, \
- DeviceNode->DevFn, PciOffset, WriteValue); \
- if(DeviceNode->ReturnCode != 0 ) { \
- PCIFR("RC##size: %02X,%02X,%02X,%04X Rtn: %04X", \
- DeviceNode->BusNumber, DeviceNode->SubBus, DeviceNode->DevFn, PciOffset,DeviceNode->ReturnCode); \
- } \
- return DeviceNode->ReturnCode; \
-}
-
- ISERIES_PCI_READ_OP( byte, Load8, u8*)
- ISERIES_PCI_READ_OP( word, Load16, u16*)
- ISERIES_PCI_READ_OP( dword,Load32, u32*)
- ISERIES_PCI_WRITE_OP(byte, Store8, u8)
- ISERIES_PCI_WRITE_OP(word, Store16,u16)
- ISERIES_PCI_WRITE_OP(dword,Store32,u32)
+struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev) {
+ struct list_head* Device_Node_Ptr;
+ int Bus, DevFn;
+
+ Device_Node_Ptr = Global_Device_List.next;
+ Bus = PciDev->bus->number;
+ DevFn = PciDev->devfn;
+
+ while(Device_Node_Ptr != &Global_Device_List) {
+ struct iSeries_Device_Node* DeviceNode = (struct iSeries_Device_Node*)Device_Node_Ptr;
+ if(Bus == DeviceNode->BusNumber && DevFn == DeviceNode->DevFn) {
+ return DeviceNode;
+ }
+ Device_Node_Ptr = Device_Node_Ptr->next;
+ }
+ return NULL;
+}
+struct iSeries_Device_Node* find_Device_Nodex(int Bus, int DevFn) {
+ struct pci_dev TempPciDev;
+ struct pci_bus TempBus;
+
+ TempBus.number = Bus;
+ TempPciDev.bus = &TempBus;
+ TempPciDev.devfn = DevFn;
+ return find_Device_Node(&TempPciDev);
+}
-/************************************************************************/
-/* Branch Table */
-/************************************************************************/
-struct pci_ops iSeries_pci_ops = {
- iSeries_pci_read_config_byte,
- iSeries_pci_read_config_word,
- iSeries_pci_read_config_dword,
- iSeries_pci_write_config_byte,
- iSeries_pci_write_config_word,
- iSeries_pci_write_config_dword
-};
-
+/**********************************************************************************
+ * check to see if the it is a pci_dev or device_node passed.
+ **********************************************************************************/
+struct iSeries_Device_Node* check_Device_Node(struct pci_dev* PciDev) {
+ struct iSeries_Device_Node* DeviceNode= (struct iSeries_Device_Node*)PciDev->sysdata;
+ if(PciDev == DeviceNode->PciDev) return DeviceNode;
+ else return find_Device_Node(PciDev);
+}
+
+/****************************************************************************
+*
+* Allocate pci_controller(phb) initialized common variables.
+*
+*****************************************************************************/
+struct pci_controller* pci_alloc_pci_controllerX(char *model, enum phb_types controller_type)
+{
+ struct pci_controller *hose;
+ PPCDBG(PPCDBG_PHBINIT, "PCI: Allocate pci_controller for %s\n",model);
+
+ hose = (struct pci_controller*)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+
+ if(hose == NULL) {
+ printk(KERN_ERR "PCI: Allocate pci_controller failed.\n");
+ return NULL;
+ }
+ memset(hose, 0, sizeof(struct pci_controller));
+ if(strlen(model) < 8) strcpy(hose->what,model);
+ else memcpy(hose->what,model,7);
+ hose->type = controller_type;
+ hose->global_number = global_phb_number;
+ global_phb_number++;
+
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+ return hose;
+}
/****************************************************************************
*
@@ -154,9 +254,8 @@
* owned or fully owned by this guest partition.
****************************************************************************/
unsigned long __init find_and_init_phbs(void) {
- struct pci_controller* hose;
+ struct pci_controller* phb;
HvBusNumber BusNumber;
- int LxBusNumber = 0; /* Linux Bus number for grins */
PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry\n");
@@ -173,37 +272,22 @@
PPCDBG(PPCDBG_BUSWALK, "Create iSeries PHB controller: %04X\n",BusNumber);
PCIFR("Create iSeries PHB controller: %04X",BusNumber);
- PPCDBG(PPCDBG_BUSWALK, "PCI: Allocate pci_controller for PBH HV\n");
- hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),GFP_KERNEL);
- if(hose == NULL) {
+ phb = pci_alloc_pci_controllerX("PHB HV", phb_type_hypervisor);
+ if(phb == NULL) {
printk("PCI: Allocate pci_controller failed.\n");
PCIFR( "PCI: Allocate pci_controller failed.\n");
return -1;
}
- memset(hose, 0, sizeof(struct pci_controller));
- *hose_tail = hose;
- hose_tail = &hose->next;
- strcpy(hose->what,"PHB HV");
- hose->type = phb_type_hypervisor;
- hose->global_number = BusNumber;
- *hose_tail = hose;
- hose_tail = &hose->next;
-
- hose->local_number = BusNumber; /* Stuff HV bus number away. */
- hose->first_busno = LxBusNumber;/* This just for debug. pcibios will */
- hose->last_busno = 0xff; /* assign the bus numbers later. */
- hose->ops = &iSeries_pci_ops; /* Cnfg Reg Ops routines. */
- LxBusNumber += 1; /* Keep track for debug. */
-
- /*********************/
- /* TCE Table for Bus */
- /*********************/
- //create_pci_bus_tce_table(BusNumber);
+ phb->pci_mem_offset =
+ phb->local_number = BusNumber; /* Stuff HV bus number away. */
+ phb->first_busno = BusNumber;
+ phb->last_busno = BusNumber;
+ phb->ops = &iSeries_pci_ops; /* Cnfg Reg Ops routines. */
/*************************************************************************
* Find and connect the devices.
*************************************************************************/
- iSeries_Scan_PHBs_Slots(hose);
+ iSeries_Scan_PHBs_Slots(phb);
}
}
@@ -216,27 +300,70 @@
*
***********************************************************************/
void iSeries_pcibios_init(void) {
+ struct pci_controller *phb;
PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry.\n");
- /* find_and_init_phbs(); comment out until debugged. */
+
+ iSeries_IoMmTable_Initialize();
+ return;
+
+ find_and_init_phbs();
+
+ PPCDBG(PPCDBG_BUSWALK,"\nList PHBs found.\n");
+ phb = hose_head;
+ while(phb != NULL) {
+ PPCDBG(PPCDBG_BUSWALK,"pci_controller(0x%016LX) for Bus 0x%02X\n",phb,phb->first_busno);
+ phb = phb->next;
+ }
+
+ PPCDBG(PPCDBG_BUSWALK,"\nList Device Tree.\n");
+ list_device_nodes();
+
+ pci_assign_all_busses = 0;
+
PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Exit.\n");
}
/***********************************************************************
* iSeries_pcibios_fixup(void)
- *
- *
- *
***********************************************************************/
void __init iSeries_pcibios_fixup(void) {
- struct pci_dev *dev;
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry.\n");
- return; /* Just return until debugged. */
+ struct pci_dev* PciDev;
+ struct iSeries_Device_Node* DeviceNode;
- pci_assign_all_busses = 0;
+ PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry.\n");
- pci_for_each_dev(dev) {
- PPCDBGCALL(PPCDBG_BUSWALK, dumpPci_Dev(dev) );
+ /******************************************************/
+ /* Fix up at the device node and pci_dev relationship */
+ /******************************************************/
+ pci_for_each_dev(PciDev) {
+ DeviceNode = find_Device_Node(PciDev);
+ if(DeviceNode != NULL) {
+ PciDev->sysdata = (void*)DeviceNode;
+ DeviceNode->PciDev = PciDev;
+ iSeries_allocateDeviceBars(PciDev);
+ } else {
+ printk("PCI: Device Tree not found for 0x%016lX\n",(unsigned long)PciDev);
+ }
}
+ iSeries_IoMmTable_Status();
+
+
+ // pci_for_each_dev(PciDev) {
+ // if (PciConfigTest(PciDev) != 0) panic("PCI: PciConfigTest Failed.\n");
+ //}
+ //iSeries_MmIoTest();
+
+ iSeries_activate_IRQs();
+}
+
+
+/***********************************************************************
+ * iSeries_pcibios_fixup_bus(int Bus)
+ *
+ ***********************************************************************/
+void iSeries_pcibios_fixup_bus(struct pci_bus* PciBus) {
+ PPCDBG(PPCDBG_BUSWALK,__FUNCTION__"(0x%04X) Entry.\n",PciBus->number);
+
}
/***********************************************************************
* find_floppy(void)
@@ -248,7 +375,7 @@
***********************************************************************/
struct pci_dev*
find_floppy() {
- PPCDBG(PPCDBG_BUSWALK,"\tFind Floppy pci_dev.. None on iSeries.\n");
+ PPCDBG(PPCDBG_BUSWALK,"- Find Floppy pci_dev.. None on iSeries.\n");
return NULL;
}
@@ -260,53 +387,13 @@
*
*
***********************************************************************/
-void
-fixup_resources(struct pci_dev *dev) {
- struct pci_controller* phb = (struct pci_controller *)dev->sysdata;
-
- PPCDBG(PPCDBG_BUSWALK, "fixup_resources:\n");
- PPCDBG(PPCDBG_BUSWALK, "\tphb = 0x%016LX\n", phb);
- PPCDBG(PPCDBG_BUSWALK, "\tphb->local_number = 0x%004X \n", phb->local_number);
+void fixup_resources(struct pci_dev *PciDev) {
+ PPCDBG(PPCDBG_BUSWALK,__FILE__" "__FUNCTION__" PciDev 0x%016X\n",PciDev);
}
-/***********************************************************************
- * build_device_node(u16 Bus, int SubBus, u8 DevFn)
- *
- *
- * char* loc-code
- * int vendor-id
- * int device-id..
- * int BusNumber
- * int SubBus
- * int ReturnCode
- *
- * int regs
- * int interrupts
- * char* loc-code
- ***********************************************************************/
-void
-build_device_node(HvBusNumber BusNumber, HvSubBusNumber SubBus, u8 DevFn) {\
- struct i_device_node* iDevice = kmalloc(sizeof(struct i_device_node), GFP_KERNEL);
- list_add_tail(&iDevice->iDevice_Chain,&iDevice_List);
-
-
-
-}
-
-void list_device_nodes(void) {
- struct list_head* iDevice_Node_Ptr = iDevice_List.next;
- int index = 1;
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry\n");
- while(iDevice_Node_Ptr != &iDevice_List) {
- iDevice_Node_Ptr = iDevice_Node_Ptr->next;
- ++index;
- }
-}
-
-
/********************************************************************************
-* Loop through each node function to find usable bridges.
+* Loop through each node function to find usable EADs bridges.
*********************************************************************************/
void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb) {
struct HvCallPci_DeviceInfo* DevInfo;
@@ -316,8 +403,6 @@
int IdSel = 1;
int MaxAgents = 8;
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry\n");
-
DevInfo = (struct HvCallPci_DeviceInfo*)kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
if(DevInfo == NULL) return;
@@ -327,18 +412,15 @@
for (IdSel=1; IdSel < MaxAgents; ++IdSel) {
HvRc = HvCallPci_getDeviceInfo(Bus, SubBus, IdSel,REALADDR(DevInfo), sizeof(struct HvCallPci_DeviceInfo));
if (HvRc == 0) {
- PPCDBG(PPCDBG_BUSWALK,"\tFound Device 0x%02X\n",DevInfo->deviceType);
if(DevInfo->deviceType == HvCallPci_NodeDevice) {
- PPCDBG(PPCDBG_BUSWALK,"\tFound EADs Bridge(NodeDevice)\n");
iSeries_Scan_EADs_Bridge(Bus, SubBus, IdSel);
}
else {
- printk("PCI: Invalid System Configuration. \n");
+ printk("PCI: Invalid System Configuration(0x%02X.\n",DevInfo->deviceType);
}
}
}
kfree(DevInfo);
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Exit\n");
}
@@ -351,8 +433,6 @@
int Function;
int HvRc;
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry\n");
-
BridgeInfo = (struct HvCallPci_BridgeInfo*)kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
if(BridgeInfo == NULL) return;
@@ -363,41 +443,45 @@
AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0);
if (HvRc == 0) {
+ /* Connect EADs: 0x18.00.12 = 0x00 */
PPCDBG(PPCDBG_BUSWALK,"Connect EADs: 0x%02X.%02X.%02X = 0x%02X\n",Bus, SubBus, AgentId);
HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId,
REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo));
if (HvRc == 0) {
- PPCDBG(PPCDBG_BUSWALK,"\tBridgeInfo..: 0x%02X.%02X.%02X = 0x%02X\n",Bus, SubBus, AgentId,
- BridgeInfo->busUnitInfo.deviceType);
-
if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) {
- PPCDBG(PPCDBG_BUSWALK,"\tScan_Bridge_Slot...: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId);
+ /* Scan_Bridge_Slot...: 0x18.00.12 */
+ //PPCDBG(PPCDBG_BUSWALK,"\tScan_Bridge_Slot...: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId);
iSeries_Scan_Bridge_Slot(Bus, BridgeInfo->subBusNumber,BridgeInfo->maxAgents);
}
+ else {
+ printk("PCI: Invalid Bridge Configuration(0x%02X)\n",BridgeInfo->busUnitInfo.deviceType);
+ }
}
}
}
kfree(BridgeInfo);
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Exit\n");
}
/********************************************************************************
*
* This assumes that the node slot is always on the primary bus!
+*
*********************************************************************************/
int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, HvSubBusNumber SubBus, int MaxAgents) {
+ struct iSeries_Device_Node* DeviceNode;
u16 VendorId = 0;
int HvRc = 0;
int Irq = 0;
int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
- int ValidSlots = 0;
+ HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
+ int FirstSlotId= 0;
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry\n");
-
+ /**********************************************************/
+ /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
+ /**********************************************************/
Irq = iSeries_allocate_IRQ(Bus, 0, AgentId);
- PPCDBG(PPCDBG_BUSWALK,"\tiSeries_allocate_IRQ.: 0x%02X.%02X.%02X(0x%02X)\n", Bus, SubBus, AgentId, Irq);
/****************************************************************************
* Connect all functions of any device found.
@@ -407,25 +491,358 @@
AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq);
if (HvRc == 0) {
- PPCDBG(PPCDBG_BUSWALK,"\tConnect....: 0x%02X.%02X.%02X Irq: 0x%02X\n",Bus, SubBus, AgentId, Irq);
HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, PCI_VENDOR_ID, &VendorId);
if (HvRc == 0) {
- PPCDBG(PPCDBG_BUSWALK,"\tVendorId...: 0x%02X.%02X.%02X = 0x%04X\n",Bus, SubBus, AgentId, VendorId);
- ++ValidSlots;
+ /**********************************************************/
+ /* FoundDevice: 0x18.28.10 = 0x12AE */
+ /**********************************************************/
+ HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq);
+ PPCDBG(PPCDBG_BUSWALK,"- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n",
+ Bus, SubBus, AgentId, VendorId);
+ ++DeviceCount;
+ PCIFR("Device(%4d): 0x%02X.%02X.%02X \n",DeviceCount,Bus, SubBus, AgentId);
+ DeviceNode = build_device_node(Bus, SubBus, EADsIdSel);
+ DeviceNode->Vendor = VendorId;
+ DeviceNode->Irq = Irq;
+
+ /***********************************************************
+ * On the first device/function, assign irq to slot
+ ***********************************************************/
+ if(Function == 0) {
+ FirstSlotId = AgentId;
+ iSeries_assign_IRQ(Irq, Bus, SubBus, AgentId);
+ PPCDBG(PPCDBG_BUSWALK,"- iSeries_assign_IRQ 0x%02X.%02X.%02X = 0x%02X\n",
+ Bus, SubBus, AgentId, Irq );
+ }
}
}
- if (HvRc != 0) {
- PPCDBG(PPCDBG_BUSWALK,"\tConnect/Read Vendor failed: 0x%02X.%02X.%02X = 0x%02X\n",Bus, SubBus, AgentId, HvRc);
- }
- }
- /****************************************************************************
- * If a device is found, assign irq to slot
- ****************************************************************************/
- if (ValidSlots > 0) {
- PPCDBG(PPCDBG_BUSWALK,"\tiSeries_assign_IRQ 0x%02X.%02X.%02X = 0x%02X\n",Bus, SubBus, AgentId, Irq );
- iSeries_assign_IRQ(Irq, Bus, SubBus, AgentId);
}
}
- PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Exit\n");
return HvRc;
+}
+/************************************************************************/
+/* I/0 Memory copy MUST use mmio commands on iSeries */
+/* To do; For performance, include the hv call directly */
+/************************************************************************/
+void* iSeries_memset(void* dest, char c, size_t Count) {
+ u8 ByteValue = c;
+ long NumberOfBytes = Count;
+ char* IoBuffer = dest;
+ while(NumberOfBytes > 0) {
+ iSeries_Write_Byte( ByteValue, (void*)IoBuffer );
+ ++IoBuffer;
+ -- NumberOfBytes;
+ }
+ return dest;
+}
+void* iSeries_memcpy_toio(void *dest, void *source, size_t count) {
+ char *dst = dest;
+ char *src = source;
+ long NumberOfBytes = count;
+ while(NumberOfBytes > 0) {
+ iSeries_Write_Byte(*src++, (void*)dst++);
+ -- NumberOfBytes;
+ }
+ return dest;
+}
+void* iSeries_memcpy_fromio(void *dest, void *source, size_t count) {
+ char *dst = dest;
+ char *src = source;
+ long NumberOfBytes = count;
+ while(NumberOfBytes > 0) {
+ *dst++ = iSeries_Read_Byte( (void*)src++);
+ -- NumberOfBytes;
+ }
+ return dest;
+}
+/**********************************************************************************
+ *
+ * Read PCI Config Space Code
+ *
+ **********************************************************************************/
+int iSeries_pci_read_config_byte(struct pci_dev* PciDev, int Offset, u8* ReadValue) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(PciDev);
+ u8 ReadData;
+ if(DeviceNode == NULL) { *ReadValue = -1; return 0x301; }
+ DeviceNode->ReturnCode = HvCallPci_configLoad8(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ Offset,&ReadData);
+ if(PciTraceFlag == 1) {
+ printk("RCB: 0x%02X.%02X 0x%04X = 0x%02X\n",DeviceNode->BusNumber,DeviceNode->DevFn,Offset,ReadData);
+ }
+ if(DeviceNode->ReturnCode != 0 ) {
+ printk("PCI: RCB (%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ PCIFR( "RCB (%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ }
+ *ReadValue = ReadData;
+ return DeviceNode->ReturnCode;
+}
+
+int iSeries_pci_read_config_word(struct pci_dev* PciDev, int Offset, u16* ReadValue) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(PciDev);
+ u16 ReadData;
+ if(DeviceNode == NULL) { *ReadValue = -1; return 0x301; }
+ DeviceNode->ReturnCode = HvCallPci_configLoad16(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ Offset,&ReadData);
+ if(PciTraceFlag == 1) {
+ printk("RCW: 0x%02X.%02X 0x%04X = 0x%04X\n",DeviceNode->BusNumber,DeviceNode->DevFn,Offset,ReadData);
+ }
+ if(DeviceNode->ReturnCode != 0 ) {
+ printk("PCI: RCW (%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ PCIFR( "RCW (%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ }
+ *ReadValue = ReadData;
+ return DeviceNode->ReturnCode;
+}
+int iSeries_pci_read_config_dword(struct pci_dev* PciDev, int Offset, u32* ReadValue) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(PciDev);
+ u32 ReadData;
+ if(DeviceNode == NULL) { *ReadValue = -1; return 0x301; }
+ DeviceNode->ReturnCode = HvCallPci_configLoad32(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ Offset,&ReadData);
+ if(PciTraceFlag == 1) {
+ printk("RCL: 0x%02X.%02X 0x%04X = 0x%08X\n",DeviceNode->BusNumber,DeviceNode->DevFn,Offset,ReadData);
+ }
+ if(DeviceNode->ReturnCode != 0 ) {
+ printk("PCI: RCL (%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ PCIFR( "RCL (%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ }
+ *ReadValue = ReadData;
+ return DeviceNode->ReturnCode;
+}
+/**********************************************************************************
+ *
+ * Write PCI Config Space Code
+ *
+ **********************************************************************************/
+int iSeries_pci_write_config_byte(struct pci_dev* PciDev, int Offset, u8 WriteData) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(PciDev);
+ if(DeviceNode == NULL) return 0x301;
+ DeviceNode->ReturnCode = HvCallPci_configStore8(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ Offset,WriteData);
+ if(PciTraceFlag == 1) {
+ printk("WCB: 0x%02X.%02X 0x%04X = 0x%02X\n",DeviceNode->BusNumber,DeviceNode->DevFn,Offset,WriteData);
+ }
+ if(DeviceNode->ReturnCode != 0 ) {
+ printk("PCI: WCB(%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ PCIFR( "WCB(%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ }
+ return DeviceNode->ReturnCode;
+}
+int iSeries_pci_write_config_word(struct pci_dev* PciDev, int Offset, u16 WriteData) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(PciDev);
+ if(DeviceNode == NULL) return 0x301;
+ DeviceNode->ReturnCode = HvCallPci_configStore16(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ Offset,WriteData);
+ if(PciTraceFlag == 1) {
+ printk("WCW: 0x%02X.%02X 0x%04X = 0x%04X\n",DeviceNode->BusNumber,DeviceNode->DevFn,Offset,WriteData);
+ }
+ if(DeviceNode->ReturnCode != 0 ) {
+ printk("PCI: WCW(%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ PCIFR( "WCW(%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ }
+ return DeviceNode->ReturnCode;
+}
+int iSeries_pci_write_config_dword(struct pci_dev* PciDev, int Offset, u32 WriteData) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(PciDev);
+ if(DeviceNode == NULL) return 0x301;
+ DeviceNode->ReturnCode = HvCallPci_configStore32(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ Offset,WriteData);
+ if(PciTraceFlag == 1) {
+ printk("WCL: 0x%02X.%02X 0x%04X = 0x%08X\n",DeviceNode->BusNumber,DeviceNode->DevFn,Offset,WriteData);
+ }
+ if(DeviceNode->ReturnCode != 0 ) {
+ printk("PCI: WCL(%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ PCIFR( "WCL(%016lX) = 0x%04X",DeviceNode->DsaAddr,DeviceNode->ReturnCode);
+ }
+ return DeviceNode->ReturnCode;
+}
+
+/************************************************************************/
+/* Branch Table */
+/************************************************************************/
+struct pci_ops iSeries_pci_ops = {
+ iSeries_pci_read_config_byte,
+ iSeries_pci_read_config_word,
+ iSeries_pci_read_config_dword,
+ iSeries_pci_write_config_byte,
+ iSeries_pci_write_config_word,
+ iSeries_pci_write_config_dword
+};
+
+int IoCounts = 0;
+int RetryMax = 7;
+/************************************************************************
+ * Check Return Code
+ * -> On Failure, print and log information.
+ * Increment Retry Count, if exceeds max, panic partition.
+ * -> If in retry, print and log success
+ ************************************************************************
+ * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
+ * PCI: Device 23.90 ReadL Retry( 1)
+ * PCI: Device 23.90 ReadL Retry Successful(1)
+ ************************************************************************/
+int CheckReturnCode(char* TextHdr, int OpCode, struct iSeries_Device_Node* DeviceNode) {
+ ++IoCounts;
+ if(DeviceNode->ReturnCode != 0) {
+ PCIFR("Device 0x%04X:%02X :%s%02d I/O Error(%2d): 0x%04X\n",
+ DeviceNode->BusNumber, DeviceNode->DevFn,TextHdr,OpCode,DeviceNode->IoRetry,DeviceNode->ReturnCode);
+ printk("Device 0x%04X:%02X :%s%02d I/O Error(%2d): 0x%04X\n",
+ DeviceNode->BusNumber, DeviceNode->DevFn,TextHdr,OpCode,DeviceNode->IoRetry,DeviceNode->ReturnCode);
+ /***************************************************************
+ * Bump the retry and check for retry count exceeded. *
+ * If, Exceeded, panic the system. *
+ ****************************************************************/
+ ++DeviceNode->IoRetry;
+ if(DeviceNode->IoRetry > RetryMax ) {
+ mf_displaySrc(0xB6000103);
+ panic_timeout = 0;
+ panic("PCI: Hardware I/O Error, SRC B6000103, Automatic Reboot Disabled.\n");
+ }
+ }
+ /********************************************************************
+ * If retry was in progress, log success and rest retry count *
+ *********************************************************************/
+ else if(DeviceNode->IoRetry > 0) {
+ DeviceNode->IoRetry = 0;
+ PCIFR("Device 0x%04X:%02X %s Retry Successful(%2d).\n",DeviceNode->BusNumber, DeviceNode->DevFn,
+ TextHdr, DeviceNode->IoRetry);
+ DeviceNode->IoRetry = 0;
+ }
+ return DeviceNode->ReturnCode;
+}
+
+/************************************************************************/
+/* helper code until Todd and Al sync up. */
+/************************************************************************/
+struct iSeries_Device_Node* xlateIoMmAddress(void* IoAddress) {
+ struct pci_dev* PciDev = iSeries_xlateIoMmAddress(IoAddress);
+ return (struct iSeries_Device_Node*)PciDev->sysdata;
+}
+
+/************************************************************************/
+/* Read MM I/O Instructions for the iSeries */
+/* On MM I/O error, all ones are returned and iSeries_pci_IoError is cal*/
+/* else, data is returned in big Endian format. */
+/************************************************************************/
+/* iSeries_Read_Byte = Read Byte ( 8 bit) */
+/* iSeries_Read_Word = Read Word (16 bit) */
+/* iSeries_Read_Long = Read Long (32 bit) */
+/************************************************************************/
+u8 iSeries_Read_Byte(void* IoAddress) {
+ u8 IoData, Data;
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(iSeries_xlateIoMmAddress(IoAddress) );
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ int BarOffset = iSeries_IoMmTable_BarOffset(IoAddress);
+
+ if(DeviceNode != 0) {
+ DeviceNode->ReturnCode = HvCallPci_barLoad8(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ BarNumber,BarOffset,&IoData);
+ Data = IoData;
+ if(PciTraceFlag == 1) {
+ printk("RDB: IoAddress 0x%016lX = 0x%02X\n",(unsigned long)IoAddress, Data);
+ }
+ if(DeviceNode->ReturnCode != 0) {
+ printk("RDB: %s Error: 0x%04X\n",DeviceNode->PciDev->slot_name,DeviceNode->ReturnCode);
+ }
+ }
+ return Data;
+}
+
+u16 iSeries_Read_Word(void* IoAddress) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(iSeries_xlateIoMmAddress(IoAddress) );
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ int BarOffset = iSeries_IoMmTable_BarOffset(IoAddress);
+ u16 IoData, Data;
+
+ if(DeviceNode != 0) {
+ DeviceNode->ReturnCode = HvCallPci_barLoad16(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ BarNumber,BarOffset,&IoData);
+ Data = swab16(IoData);
+
+ if(PciTraceFlag == 1) {
+ printk("RDW: IoAddress 0x%016lX = 0x%04X\n",(unsigned long)IoAddress, Data);
+ }
+ if(DeviceNode->ReturnCode != 0) {
+ printk("RDW: %s Error: 0x%04X\n",DeviceNode->PciDev->slot_name,DeviceNode->ReturnCode);
+ }
+ }
+ return Data;
+}
+u32 iSeries_Read_Long(void* IoAddress) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(iSeries_xlateIoMmAddress(IoAddress) );
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ int BarOffset = iSeries_IoMmTable_BarOffset(IoAddress);
+ u32 IoData, Data;
+
+ if(DeviceNode != 0) {
+ DeviceNode->ReturnCode = HvCallPci_barLoad32(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ BarNumber,BarOffset,&IoData);
+ Data = swab32(IoData);
+
+ if(PciTraceFlag == 1) {
+ printk("RDL: IoAddress 0x%016lX = 0x%08X\n",(unsigned long)IoAddress, Data);
+ }
+ if(DeviceNode->ReturnCode != 0) {
+ printk("RDL: %s Error: 0x%04X\n",DeviceNode->PciDev->slot_name,DeviceNode->ReturnCode);
+ }
+ }
+ return Data;
+}
+/************************************************************************/
+/* Write MM I/O Instructions for the iSeries */
+/************************************************************************/
+/* iSeries_Write_Byte = Write Byte (8 bit) */
+/* iSeries_Write_Word = Write Word(16 bit) */
+/* iSeries_Write_Long = Write Long(32 bit) */
+/************************************************************************/
+void iSeries_Write_Byte(u8 Data, void* IoAddress) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(iSeries_xlateIoMmAddress(IoAddress) );
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ int BarOffset = iSeries_IoMmTable_BarOffset(IoAddress);
+ u16 IoData = Data;
+
+ if(DeviceNode != 0 && BarNumber != -1) {
+ DeviceNode->ReturnCode = HvCallPci_barStore8 (DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ BarNumber,BarOffset,IoData);
+ if(PciTraceFlag == 1) {
+ printk("WWB: IoAddress 0x%016lX = 0x%02X\n",(unsigned long)IoAddress,Data);
+ }
+ if(DeviceNode->ReturnCode != 0) {
+ printk("WWB: %s Error: 0x%04X\n",DeviceNode->PciDev->slot_name,DeviceNode->ReturnCode);
+ }
+ }
+}
+void iSeries_Write_Word(u16 Data, void* IoAddress) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(iSeries_xlateIoMmAddress(IoAddress) );
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ int BarOffset = iSeries_IoMmTable_BarOffset(IoAddress);
+ u16 IoData = swab16(Data);
+
+ if(DeviceNode != 0 ) {
+ DeviceNode->ReturnCode = HvCallPci_barStore16(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ BarNumber,BarOffset,IoData);
+ if(PciTraceFlag == 1) {
+ printk("WWW: IoAddress 0x%016lX = 0x%04X\n",(unsigned long)IoAddress,Data);
+ }
+ if(DeviceNode->ReturnCode != 0) {
+ printk("WWW: %s Error: 0x%04X\n",DeviceNode->PciDev->slot_name,DeviceNode->ReturnCode);
+ }
+ }
+}
+void iSeries_Write_Long(u32 Data, void* IoAddress) {
+ struct iSeries_Device_Node* DeviceNode = check_Device_Node(iSeries_xlateIoMmAddress(IoAddress) );
+ int BarNumber = iSeries_IoMmTable_Bar(IoAddress);
+ int BarOffset = iSeries_IoMmTable_BarOffset(IoAddress);
+ u32 IoData = swab32(Data);
+
+ if(DeviceNode != 0 && BarNumber != -1) {
+ DeviceNode->ReturnCode = HvCallPci_barStore32(DeviceNode->BusNumber,DeviceNode->SubBus,0x10,
+ BarNumber,BarOffset,IoData);
+ if(PciTraceFlag == 1) {
+ printk("WWL: IoAddress 0x%016lX = 0x%08X\n",(unsigned long)IoAddress, Data);
+ }
+ if(DeviceNode->ReturnCode != 0) {
+ printk("WWL: %s Error: 0x%04X\n",DeviceNode->PciDev->slot_name,DeviceNode->ReturnCode);
+ }
+ }
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_setup.c linuxppc64_2_4/arch/ppc64/kernel/iSeries_setup.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/iSeries_setup.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/iSeries_setup.c Thu Sep 13 11:54:36 2001
@@ -48,7 +48,6 @@
#include
#include
#include
-#include
/* Function Prototypes */
@@ -59,6 +58,9 @@
void build_valid_hpte( unsigned long vsid, unsigned long ea, unsigned long pa,
pte_t * ptep, unsigned hpteflags, unsigned bolted );
extern void ppcdbg_initialize(void);
+extern void iSeries_pcibios_init(void);
+extern void iSeries_pcibios_fixup(void);
+extern void iSeries_pcibios_fixup_bus(int);
/* Global Variables */
@@ -77,6 +79,7 @@
extern struct Naca *naca;
extern int rd_size; /* Defined in drivers/block/rd.c */
extern unsigned long klimit;
+static int mf_initialized = 0;
/*
* void __init iSeries_init_early()
@@ -85,7 +88,7 @@
void __init
iSeries_init_early(void)
{
-
+#ifdef CONFIG_PPC_ISERIES
ppcdbg_initialize();
#if defined(CONFIG_BLK_DEV_INITRD)
@@ -107,19 +110,9 @@
#endif /* CONFIG_BLK_DEV_INITRD */
{
- ROOT_DEV = MKDEV( VIODASD_MAJOR, 1 );
+ /* ROOT_DEV = MKDEV( VIODASD_MAJOR, 1 ); */
}
- /* Initialize the table which translate Linux physical addresses to
- * AS/400 absolute addresses
- */
-
- build_iSeries_Memory_Map();
-
- setup_iSeries_cache_sizes();
-
- /* Initialize machine-dependency vectors */
-
ppc_md.setup_arch = iSeries_setup_arch;
ppc_md.setup_residual = iSeries_setup_residual;
ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
@@ -128,6 +121,9 @@
ppc_md.get_irq = iSeries_get_irq;
ppc_md.init = NULL;
+ ppc_md.pcibios_fixup = iSeries_pcibios_fixup;
+ ppc_md.pcibios_fixup_bus = iSeries_pcibios_fixup_bus;
+
ppc_md.restart = iSeries_restart;
ppc_md.power_off = iSeries_power_off;
ppc_md.halt = iSeries_halt;
@@ -149,11 +145,27 @@
ppc_md.ppc_kbd_sysrq_xlate = NULL;
#endif
- if ( itLpNaca.xPirEnvironMode == 0 )
- piranha_simulator = 1;
+ htpe_init_iSeries();
+ tce_init_iSeries();
+
+ /* Initialize the table which translate Linux physical addresses to
+ * AS/400 absolute addresses
+ */
+
+ build_iSeries_Memory_Map();
+
+ setup_iSeries_cache_sizes();
+
+ /* Initialize machine-dependency vectors */
- return;
+#ifdef CONFIG_SMP
+ smp_init_iSeries();
+#endif
+
+ if ( itLpNaca.xPirEnvironMode == 0 )
+ piranha_simulator = 1;
+#endif
}
/*
@@ -188,15 +200,12 @@
iSeries_proc_early_init();
mf_init();
+ mf_initialized = 1;
+ mb();
iSeries_proc_callback( &pmc_proc_init );
-
- viopath_init();
-
- return;
}
-
/*
* The iSeries may have very large memories ( > 128 GB ) and a partition
* may get memory in "chunks" that may be anywhere in the 2**52 real
@@ -514,7 +523,7 @@
return (len);
}
-#ifdef CONFIG_SMP
+#if 0
void iSeries_spin_lock(spinlock_t *lock)
{
int i;
@@ -528,7 +537,7 @@
}
}
HMT_medium();
- HvCallCfg_getLps();
+ ALLOW_HYPERVISOR_PREEMPTION;
}
}
@@ -545,7 +554,7 @@
}
}
HMT_medium();
- HvCallCfg_getLps();
+ ALLOW_HYPERVISOR_PREEMPTION;
}
}
@@ -562,7 +571,7 @@
}
}
HMT_medium();
- HvCallCfg_getLps();
+ ALLOW_HYPERVISOR_PREEMPTION;
}
}
@@ -579,7 +588,7 @@
}
HMT_medium();
- HvCallCfg_getLps();
+ ALLOW_HYPERVISOR_PREEMPTION;
}
}
@@ -628,12 +637,12 @@
* Document me.
* and Implement me.
*/
-void __init
-iSeries_init_IRQ(void)
-{
- return;
-}
-
+//void __init
+//iSeries_init_IRQ(void)
+//{
+// return;
+//}
+//
/*
* Document me.
* and Implement me.
@@ -753,8 +762,10 @@
iSeries_progress( char * st, unsigned short code )
{
printk( "Progress: [%04x] - %s\n", (unsigned)code, st );
-#if 0
- if ( !piranha_simulator )
+ if ( !piranha_simulator && mf_initialized ) {
+ if (code != 0xffff)
mf_displayProgress( code );
-#endif
+ else
+ mf_clearSrc();
+ }
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/irq.c linuxppc64_2_4/arch/ppc64/kernel/irq.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/irq.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/irq.c Sat Sep 15 22:35:39 2001
@@ -23,14 +23,6 @@
* instead of just grabbing them. Thus setups with different IRQ numbers
* shouldn't result in any weird surprises, and installing new handlers
* should be easier.
- *
- * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the
- * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit
- * mask register (of which only 16 are defined), hence the weird shifting
- * and compliment of the cached_irq_mask. I want to be able to stuff
- * this right into the SIU SMASK register.
- * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
- * to reduce code space and undefined function references.
*/
@@ -83,9 +75,6 @@
int ppc_spurious_interrupts = 0;
struct irqaction *ppc_irq_action[NR_IRQS];
-unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
-unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
-atomic_t ppc_n_lost_interrupts;
unsigned long lpEvent_count = 0;
#ifdef CONFIG_XMON
extern void xmon(struct pt_regs *regs);
@@ -565,7 +554,7 @@
}
#endif /* CONFIG_SMP */
lpq = paca->lpQueuePtr;
- if ( lpq )
+ if ( lpq && ItLpQueue_isLpIntPending( lpq ) )
lpEvent_count += ItLpQueue_process( lpq, regs );
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/local_irq.h linuxppc64_2_4/arch/ppc64/kernel/local_irq.h
--- linux-2.4.9-ac10/arch/ppc64/kernel/local_irq.h Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/local_irq.h Sat Sep 15 22:35:39 2001
@@ -22,8 +22,5 @@
extern int ppc_spurious_interrupts;
extern int ppc_second_irq;
extern struct irqaction *ppc_irq_action[NR_IRQS];
-extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
-extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
-extern atomic_t ppc_n_lost_interrupts;
#endif /* _PPC_KERNEL_LOCAL_IRQ_H */
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/misc.S linuxppc64_2_4/arch/ppc64/kernel/misc.S
--- linux-2.4.9-ac10/arch/ppc64/kernel/misc.S Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/misc.S Fri Sep 14 20:12:59 2001
@@ -27,6 +27,10 @@
#include
#include "ppc_asm.h"
+#ifdef CONFIG_PPC_ISERIES
+#define DO_SOFT_DISABLE
+#endif
+
.text
/*
@@ -63,13 +67,15 @@
mr r3,r1
blr
-_GLOBAL(get_paca)
- mfspr r3,SPRG3;
- blr
-
+#ifdef CONFIG_PPC_ISERIES
/* void __no_use_save_flags(unsigned long *flags) */
_GLOBAL(__no_use_save_flags)
+#ifdef DO_SOFT_DISABLE
+ mfspr r4,SPRG3
+ lbz r4,PACAPROCENABLED(r4)
+#else
mfmsr r4
+#endif
std r4,0(r3)
blr
@@ -81,6 +87,10 @@
* sense anyway.
* -- Cort
*/
+#ifdef DO_SOFT_DISABLE
+ mfspr r6,SPRG3
+ lbz r5,PACAPROCENABLED(r6)
+#else
mfmsr r5
mr r4,r3
mr r3,r5
@@ -88,59 +98,56 @@
/* Copy all except the MSR_EE bit from r4 (current MSR value)
to r3. This is the sort of thing the rlwimi instruction is
designed for. -- paulus. */
+#endif
/* Check if things are setup the way we want _already_. */
cmpw 0,r3,r5
beqlr
/* are we enabling interrupts? */
+#ifdef DO_SOFT_DISABLE
+ cmpi 0,r3,0
+ stb r3,PACAPROCENABLED(r6)
+#else
rlwinm. r0,r3,0,16,16
+ mtmsrd r3
+#endif
beq 1f
- /* Check pending interrupts
- * A decrementer, IPI or PMC interrupt may have occurred
- * while we were in the hypervisor (which enables)
- */
+ /* Check pending interrupts */
CHECKANYINT(r4,r5)
beq+ 1f
/*
* Handle pending interrupts in interrupt context
*/
- mtmsrd r3
li r0,0x5555
- sc
- blr
+ sc
1:
- sync
- mtmsrd r3
- isync
- blr
-/* void __no_lpq_restore_flags(unsigned long flags) */
-_GLOBAL(__no_lpq_restore_flags)
- mfmsr r5
- mr r4,r3
- mr r3,r5
- rlwimi r3,r4,0,16,16
- /* Copy all except the MSR_EE bit from r4 (current MSR value)
- to r3. This is the sort of thing the rlwimi instruction is
- designed for. -- paulus. */
- /* Check if things are setup the way we want _already_. */
- cmpw 0,r3,r5
- beqlr
- sync
- mtmsrd r3
- isync
blr
_GLOBAL(__no_use_cli)
+#ifdef DO_SOFT_DISABLE
+ mfspr r5,SPRG3
+ lbz r3,PACAPROCENABLED(r5)
+ li r4,0
+ stb r4,PACAPROCENABLED(r5)
+#else
mfmsr r0 /* Get current interrupt state */
rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
rldicl r0,r0,48,1
rldicl r0,r0,16,0 /* clear MSR_EE in r0 */
mtmsrd r0 /* Update machine state */
+#endif
blr /* Done */
_GLOBAL(__no_use_sti)
+#ifdef DO_SOFT_DISABLE
+ mfspr r6,SPRG3
+ li r3,1
+ stb r3,PACAPROCENABLED(r6)
+#else
mfmsr r3 /* Get current state */
ori r3,r3,MSR_EE /* Turn on 'EE' bit */
+ mtmsrd r3
+#endif
/* Check for pending interrupts
* A decrementer, IPI or PMC interrupt may have occurred
@@ -152,39 +159,11 @@
/*
* Handle pending interrupts in interrupt context
*/
- mtmsrd r3
li r0,0x5555
sc
- blr
1:
- sync /* Some chip revs have problems here... */
- mtmsrd r3 /* Update machine state */
blr
-
-/*
- * We were about to enable interrupts but we have to simulate
- * some interrupts that were lost by enable_irq first.
- */
-#if 0
-_GLOBAL(do_fake_interrupt)
- mflr r0
- std r0,16(r1)
- std r3,-8(r1)
- stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1)
-1: bl .fake_interrupt
- /* Check for pending interrupt
- * A decrementer, IPI or PMC interrupt may have occurred
- * while we were in the hypervisor (which enables)
- */
- CHECKANYINT(r4,r5)
- bne- 1b
- addi r1,r1,STACK_FRAME_OVERHEAD+16
- ld r3,-8(r1)
- ld r0,16(r1)
- mtlr r0
- mtmsrd r3
- blr
-#endif
+#endif
/*
* complement mask on the msr then "or" some values on.
* _nmask_and_or_msr(nmask, value_to_or)
@@ -308,11 +287,10 @@
* Flush a particular page from the data cache to RAM.
* Note: this is necessary because the instruction cache does *not*
* snoop from the data cache.
- * This is a no-op on the 601 which has a unified cache.
*
- * void __flush_page_to_ram(void *page)
+ * void __flush_dcache_icache(void *page)
*/
-_GLOBAL(__flush_page_to_ram)
+_GLOBAL(__flush_dcache_icache)
/*
* Flush the data cache to memory
*
@@ -344,126 +322,25 @@
isync
blr
-
-/*
- * Flush a particular page from the instruction cache.
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- *
- * void __flush_icache_page(void *page)
- */
-_GLOBAL(__flush_icache_page)
/*
- * Different systems have different cache line sizes
+ * Copy a whole page. Assumes a 4096B page size.
*/
-
-/* Invalidate the icache */
-
- LOADADDR(r6,naca)
- ld r6,0(r6)
- clrrdi r3,r3,12 /* Page align */
- lhz r4,ICACHEL1LINESPERPAGE(r6) /* Get # icache lines per page */
- lhz r5,ICACHEL1LINESIZE(r6) /* Get icache line size */
- mtctr r4
-1: icbi 0,r3
- add r3,r3,r5
- bdnz 1b
- sync
- isync
- blr
-
-/*
- * Clear a page using the dcbz instruction, which doesn't cause any
- * memory traffic (except to write out any cache lines which get
- * displaced). This only works on cacheable memory.
- */
-_GLOBAL(clear_page)
- LOADADDR(r6,naca)
- ld r6,0(r6)
- clrrdi r3,r3,12 /* Page align */
- lhz r4,DCACHEL1LINESPERPAGE(r6) /* Get # dcache lines per page */
- lhz r5,DCACHEL1LINESIZE(r6) /* Get dcache line size */
- mtctr r4
-0: dcbz 0,r3
- add r3,r3,r5
- bdnz 0b
- blr
-
-/*
- * Copy a whole page. We use the dcbz instruction on the destination
- * to reduce memory traffic (it eliminates the unnecessary reads of
- * the destination into cache). This requires that the destination
- * is cacheable.
- */
-#define COPY_32_BYTES \
- ld r6,8(r4); \
- ld r7,16(r4); \
- ld r8,24(r4); \
- ldu r9,32(r4); \
- std r6,8(r3); \
- std r7,16(r3); \
- std r8,24(r3); \
- stdu r9,32(r3)
-
_GLOBAL(copy_page)
-
LOADADDR(r9,naca)
ld r9,0(r9)
clrrdi r3,r3,12 /* Page align */
clrrdi r4,r4,12 /* Page align */
- lhz r5,DCACHEL1LINESPERPAGE(r9) /* Get # dcache lines per page */
- lhz r0,DCACHEL1LINESIZE(r9) /* Get dcache line size */
+ li r5,256
mtctr r5
addi r3,r3,-8
addi r4,r4,-8
- li r10,8
- cmpi 0,r0,32
- beq do_32_byte_line
- cmpi 0,r0,64
- beq do_64_byte_line
- cmpi 0,r0,128
- beq do_128_byte_line
-
- /* We don't have code specifically for this cache line size */
- /* Assume that the cache line size is at least 32 (and of */
- /* course a multiple of 32) */
- /* This code will work for all power-of-2 cache line sizes */
- /* from 32 to 4096 */
-
-1: mr r5,r0
- dcbz r10,r3
-0: COPY_32_BYTES
- addi r5,r5,-32
- or. r5,r5,r5
- bne 0b
- bdnz 1b
- blr
-
- .globl do_32_byte_line
-do_32_byte_line:
- dcbz r10,r3
- COPY_32_BYTES
- bdnz do_32_byte_line
- blr
-
- .globl do_64_byte_line
-do_64_byte_line:
- dcbz r10,r3
- COPY_32_BYTES
- COPY_32_BYTES
- bdnz do_64_byte_line
- blr
-
- .globl do_128_byte_line
-do_128_byte_line:
- dcbz r10,r3
- COPY_32_BYTES
- COPY_32_BYTES
- COPY_32_BYTES
- COPY_32_BYTES
- bdnz do_128_byte_line
- blr
+1: ld r6,8(r4)
+ ldu r7,16(r4)
+ std r6,8(r3)
+ stdu r7,16(r3)
+ bdnz+ 1b
+ blr
/*
* I/O string operations
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/mk_defs.c linuxppc64_2_4/arch/ppc64/kernel/mk_defs.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/mk_defs.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/mk_defs.c Thu Sep 13 10:16:37 2001
@@ -69,13 +69,15 @@
DEFINE(PACASTABREAL, offsetof(struct Paca, xStab_data.real));
DEFINE(PACASTABVIRT, offsetof(struct Paca, xStab_data.virt));
DEFINE(PACAR1, offsetof(struct Paca, xR1));
- DEFINE(PACAR21, offsetof(struct Paca, xR21));
- DEFINE(PACAR22, offsetof(struct Paca, xR22));
- DEFINE(PACACCR, offsetof(struct Paca, xCCR));
DEFINE(PACALPQUEUE, offsetof(struct Paca, lpQueuePtr));
- DEFINE(PACALPPACA, offsetof(struct Paca, xLpPaca));
DEFINE(PACATOC, offsetof(struct Paca, xTOC));
+ DEFINE(PACAEXCSP, offsetof(struct Paca, exception_sp));
+ DEFINE(PACAPROCENABLED, offsetof(struct Paca, xProcEnabled));
+ DEFINE(PACADEFAULTDECR, offsetof(struct Paca, default_decr));
+ DEFINE(PACALPPACA, offsetof(struct Paca, xLpPaca));
DEFINE(LPPACA, offsetof(struct Paca, xLpPaca));
+ DEFINE(PACAREGSAV, offsetof(struct Paca, xRegSav));
+ DEFINE(PACAEXC, offsetof(struct Paca, exception_stack));
DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0));
DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt));
@@ -132,6 +134,7 @@
DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
+ DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe));
DEFINE(CLONE_VM, CLONE_VM);
return 0;
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/open_pic.c linuxppc64_2_4/arch/ppc64/kernel/open_pic.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/open_pic.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/open_pic.c Fri Aug 31 15:48:52 2001
@@ -87,10 +87,10 @@
*/
#ifdef CONFIG_SMP
#define THIS_CPU Processor[cpu]
-#define DECL_THIS_CPU int cpu = cpu_hw_index[smp_processor_id()]
+#define DECL_THIS_CPU int cpu = hard_smp_processor_id()
#define CHECK_THIS_CPU check_arg_cpu(cpu)
#else
-#define THIS_CPU Processor[cpu_hw_index[0]]
+#define THIS_CPU Processor[hard_smp_processor_id()]
#define DECL_THIS_CPU
#define CHECK_THIS_CPU
#endif /* CONFIG_SMP */
@@ -358,7 +358,7 @@
/* SIOint (8259 cascade) is special */
if (offset) {
openpic_initirq(0, 8, offset, 1, 1);
- openpic_mapirq(0, 1<>= 1)
- mask |= (cpumask & 1) << cpu_hw_index[i];
+ mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
return mask;
}
@@ -595,7 +595,7 @@
{
#ifdef CONFIG_IRQ_ALL_CPUS
int i;
- u32 msk = 1 << cpu_hw_index[smp_processor_id()];
+ u32 msk = 1 << hard_smp_processor_id();
#endif
spin_lock(&openpic_setup_lock);
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pSeries_pci.c linuxppc64_2_4/arch/ppc64/kernel/pSeries_pci.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/pSeries_pci.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/pSeries_pci.c Sun Sep 16 20:14:16 2001
@@ -46,16 +46,6 @@
#include "open_pic.h"
#include "pci.h"
-/* Supporting macros *********************************************/
-#define TESTBIT(value,bits) ((value&bits) == bits)
-#define TRUE 1
-#define FALSE 0
-
-extern struct pci_controller* hose_head;
-extern struct pci_controller** hose_tail;
-extern struct Naca *naca;
-extern struct pci_ops rtas_pci_ops;
-extern struct pci_ops ibm_phb_pci_ops;
extern struct device_node *allnodes;
extern unsigned long phb_tce_table_init(struct pci_controller *phb);
@@ -65,33 +55,69 @@
unsigned long find_and_init_phbs(void);
struct pci_controller* alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) ;
void pSeries_pcibios_fixup(void);
-void pci_build_bar_resources(struct pci_dev* Pci_Dev, int BarCount);
-void pci_build_rom_resources(struct pci_dev* Pci_Dev);
-void pci_set_BARS(struct pci_dev* Pci_Dev);
/**********************************************************************************
*
* pSeries I/O Operations to access the PCI configuration space.
*
**********************************************************************************/
-#define RTAS_PCI_READ_OP(size, type, nbytes) \
-int __chrp \
-rtas_read_config_##size(struct pci_dev *dev, int offset, type val) { \
- unsigned long ReturnValue, ConfigAddr; \
- int ReturnCode; \
- ConfigAddr = ((dev->bus->number&0x0000FF) << 16) | (dev->devfn << 8) | (offset & 0xff); \
- ReturnCode = call_rtas("read-pci-config", 2, 2, &ReturnValue, ConfigAddr, nbytes);\
- *val = ReturnValue; \
- return ReturnCode; \
-}
-#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
-int __chrp \
-rtas_write_config_##size(struct pci_dev *dev, int offset, type val) { \
- unsigned long ConfigAddr; \
- int ReturnCode; \
- ConfigAddr = ((dev->bus->number&0x0000FF) << 16) | (dev->devfn << 8) | (offset & 0xff); \
- ReturnCode = call_rtas("write-pci-config", 3, 1, NULL, ConfigAddr, nbytes, (ulong)val); \
- return ReturnCode; \
+#define RTAS_PCI_READ_OP(size, type, nbytes) \
+int __chrp \
+rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
+ unsigned long returnval = ~0L; \
+ unsigned long buid; \
+ unsigned int addr; \
+ int ret; \
+ \
+ if (dn == NULL) { \
+ ret = -2; \
+ } else if (dn->status) { \
+ ret = -1; \
+ } else { \
+ addr = (dn->busno << 16) | (dn->devfn << 8) | offset; \
+ buid = dn->phb->buid; \
+ if (buid) { \
+ ret = call_rtas("ibm,read-pci-config", 4, 2, &returnval, addr, buid >> 32, buid & 0xffffffff, nbytes); \
+ } else { \
+ ret = call_rtas("read-pci-config", 2, 2, &returnval, addr, nbytes); \
+ } \
+ } \
+ *val = returnval; \
+ return ret; \
+} \
+int __chrp \
+rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
+ struct device_node *dn = pci_device_to_OF_node(dev); \
+ int ret = rtas_read_config_##size(dn, offset, val); \
+ /* udbg_printf("read bus=%x, devfn=%x, ret=%d phb=%lx, dn=%lx\n", dev->bus->number, dev->devfn, ret, dn ? dn->phb : 0, dn); */ \
+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; \
+}
+
+#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
+int __chrp \
+rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
+ unsigned long buid; \
+ unsigned int addr; \
+ int ret; \
+ \
+ if (dn == NULL) { \
+ ret = -2; \
+ } else if (dn->status) { \
+ ret = -1; \
+ } else { \
+ buid = dn->phb->buid; \
+ addr = (dn->busno << 16) | (dn->devfn << 8) | offset; \
+ if (buid) { \
+ ret = call_rtas("ibm,write-pci-config", 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, nbytes, (ulong) val); \
+ } else { \
+ ret = call_rtas("write-pci-config", 3, 1, NULL, addr, nbytes, (ulong)val); \
+ } \
+ } \
+ return ret; \
+} \
+int __chrp \
+rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \
+ return rtas_write_config_##size(pci_device_to_OF_node(dev), offset, val); \
}
RTAS_PCI_READ_OP(byte, u8 *, 1)
@@ -102,75 +128,14 @@
RTAS_PCI_WRITE_OP(dword, u32, 4)
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,
- pci_read_bar_registers,
- pci_read_irq_line
-};
-
-/**********************************************************************************
- *
- * pSeries I/O Operations to access the PCI configuration space.
- * This is the support for Large Systems(>256 buses).
- *
- **********************************************************************************/
-#define RTAS64_PCI_READ_OP(size, type, nbytes) \
-int __chrp \
-rtas64_read_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- struct pci_controller *hose = dev->sysdata; \
- unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
- | (((dev->bus->number) & 0xff) << 16); \
- unsigned long ret = ~0UL; \
- int rval; \
- int buidhi = hose->buid >> 32; \
- int buidlo = hose->buid & 0xffffffff; \
- \
- rval = call_rtas("ibm,read-pci-config", 4, 2, &ret, \
- addr, buidhi, buidlo, nbytes); \
- *val = ret; \
- /* udbg_printf("%08x %08x SYM Read Config %d\n",addr, ret,rval); */ \
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
-}
-
-#define RTAS64_PCI_WRITE_OP(size, type, nbytes) \
-int __chrp \
-rtas64_write_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- struct pci_controller *hose = dev->sysdata; \
- unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
- | (((dev->bus->number) & 0xff) << 16); \
- int rval; \
- int buidhi = hose->buid >> 32; \
- int buidlo = hose->buid & 0xffffffff; \
- \
- rval = call_rtas("ibm,write-pci-config", 5, 1, NULL, \
- addr, buidhi, buidlo, nbytes, (ulong)val); \
- /* udbg_printf("%08x %08x SYM Write Config %d\n",addr, val,rval); */ \
- return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
-}
-
-RTAS64_PCI_READ_OP(byte, u8 *, 1)
-RTAS64_PCI_READ_OP(word, u16 *, 2)
-RTAS64_PCI_READ_OP(dword, u32 *, 4)
-RTAS64_PCI_WRITE_OP(byte, u8, 1)
-RTAS64_PCI_WRITE_OP(word, u16, 2)
-RTAS64_PCI_WRITE_OP(dword, u32, 4)
-
-struct pci_ops rtas64_pci_ops = {
- rtas64_read_config_byte,
- rtas64_read_config_word,
- rtas64_read_config_dword,
- rtas64_write_config_byte,
- rtas64_write_config_word,
- rtas64_write_config_dword
+ rtas_pci_read_config_byte,
+ rtas_pci_read_config_word,
+ rtas_pci_read_config_dword,
+ rtas_pci_write_config_byte,
+ rtas_pci_write_config_word,
+ rtas_pci_write_config_dword,
};
-
/******************************************************************
* pci_read_irq_line
*
@@ -204,216 +169,6 @@
PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",Pci_Dev->slot_name,Pci_Dev->irq);
return 0;
}
-/******************************************************************
- * pci_set_BARS
- *
- * Sets the IOA BAR registers from the values from the register
- * values found in the OpenFirmware node for the device. Or in
- * the future, assigns space in phb and sets the values.
- ******************************************************************/
-void
-pci_set_BARS(struct pci_dev* Pci_Dev) {
- int AddrIndex;
- struct device_node *Device_Node = pci_device_to_OF_node(Pci_Dev);
-
- if(Device_Node == 0 || Device_Node->n_addrs == 0 || Device_Node->addrs == NULL) {
- PPCDBG(PPCDBG_BUSWALK, "\tDevice Node was not found or no defined bars\n");
- return;
- }
- PPCDBG(PPCDBG_BUSWALK, "\tSet Bar Regs(%d)\n",Device_Node->n_addrs);
- for(AddrIndex = 0; AddrIndex < Device_Node->n_addrs; ++AddrIndex) {
- int PciReg = (Device_Node->addrs[AddrIndex].space & 0x000000FF);
- u32 PciBar = Device_Node->addrs[AddrIndex].address;
- int BarSze = Device_Node->addrs[AddrIndex].size;
-
- PPCDBG(PPCDBG_BUSWALK, "\tPciBar 0x%02X, 0x%08X, 0x%08X\n",PciReg,PciBar,BarSze);
- pci_write_config_dword(Pci_Dev, PciReg,PciBar);
- }
-}
-/******************************************************************
- *
- * pci_build_bar_registers
- *
- * This function will build the resources based on the information
- * that is extracted from the BAR register. The original BAR value
- * is saved and restored.
- *
- * Note: This is pSeries brand specific code.
- * In the future, this code will be setting the initial BAR
- * value and handing out the memory space in the PHB.
- ******************************************************************/
-void
-pci_build_bar_resources(struct pci_dev* Pci_Dev, int Count) {
- int BarRegister = PCI_BASE_ADDRESS_0;
- int EndingBar = BarRegister + (Count*4);
- int ResourceIndex = 0;
- PPCDBG(PPCDBG_BUSWALK, "\npci_read_bar_registers %s\n",Pci_Dev->slot_name);
-
- /**************************************************************
- * Read Bars until the ending bar has been read.
- **************************************************************/
- for(BarRegister = PCI_BASE_ADDRESS_0;BarRegister <= EndingBar; BarRegister += 4) {
- struct resource* Resource = &Pci_Dev->resource[ResourceIndex];
- u32 BarSaveArea, BarSizeBits, BarSize;
- u64 BarStart;
- /**********************************************************
- * Save the original bar value and check for success.
- **********************************************************/
- if((pci_read_config_dword( Pci_Dev, BarRegister, &BarSaveArea) != 0) ||
- (BarSaveArea == 0xFFFFFFFF )) {
- BarRegister += 4;
- continue;
- }
- /**********************************************************
- * Write all ones to register to get the size of area.
- **********************************************************/
- pci_write_config_dword(Pci_Dev, BarRegister, 0xFFFFFFFF);
- pci_read_config_dword( Pci_Dev, BarRegister, &BarSizeBits);
- pci_write_config_dword(Pci_Dev, BarRegister, BarSaveArea);
-
- /**********************************************************
- * Error reading bar(all ones back) or unimplemented BAR(zero)
- **********************************************************/
- if(( BarSizeBits == 0xFFFFFFFF ) || BarSizeBits == 0 ) {
- BarRegister += 4;
- continue;
- }
- Resource->name = Pci_Dev->name;
- /**********************************************************
- * Test and read Io Space, It is always 32 bits.
- **********************************************************/
- if(TESTBIT(BarSizeBits,PCI_BASE_ADDRESS_SPACE_IO) == TRUE) {
- BarSize = (~(BarSizeBits&PCI_BASE_ADDRESS_IO_MASK)) +1;
- Resource->flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
- Resource->start = BarSaveArea & PCI_BASE_ADDRESS_IO_MASK;
- Resource->end = Resource->start + BarSize - 1;
- ++ResourceIndex;
- }
- /**********************************************************
- * Memory Space, could be 32 bits or 64 bits
- **********************************************************/
- else {
- Resource->flags = IORESOURCE_MEM;
- if( TESTBIT(BarSizeBits,PCI_BASE_ADDRESS_MEM_PREFETCH) == TRUE) {
- Resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
- }
- BarStart = BarSaveArea &PCI_BASE_ADDRESS_MEM_MASK;
- BarSize = ~((BarSizeBits)&PCI_BASE_ADDRESS_MEM_MASK)+1;
- /**********************************************************
- * 64 bit register, read next register to get the high 32
- * bits. PCI Spec says to write both and THEN read.
- **********************************************************/
- if( TESTBIT(BarSizeBits,PCI_BASE_ADDRESS_MEM_TYPE_64) == TRUE) {
- u64 High64Bits;
- u32 BarHigh64Save;
- Resource->flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
- BarRegister += 4; /* Index to next Bar */
- pci_read_config_dword( Pci_Dev, BarRegister, &BarHigh64Save);
- High64Bits = BarHigh64Save;
- BarStart += (High64Bits<< 32);
- pci_write_config_dword(Pci_Dev, BarRegister-4,0xFFFFFFFF);
- pci_write_config_dword(Pci_Dev, BarRegister, 0xFFFFFFFF);
- pci_read_config_dword( Pci_Dev, BarRegister-4,&BarSizeBits);
- BarSize = ~((BarSizeBits)&PCI_BASE_ADDRESS_MEM_MASK)+1;
- pci_read_config_dword( Pci_Dev, BarRegister, &BarSizeBits);
- High64Bits = ~(BarSizeBits);
- BarSize += (High64Bits << 32);
- pci_write_config_dword(Pci_Dev, BarRegister-4,BarSaveArea);
- pci_write_config_dword(Pci_Dev, BarRegister, BarHigh64Save);
- ++ResourceIndex; /* Skip next resource */
- }
- /**********************************************************
- * Set resource fields with values.
- **********************************************************/
- Resource->start = BarStart;
- Resource->end = BarStart + BarSize - 1;
- ++ResourceIndex;
- }
- }
- PPCDBGCALL(PPCDBG_BUSWALK, dumpPci_Dev(Pci_Dev) );
-}
-/******************************************************************
- *
- * Read the rom register
- *
- ******************************************************************/
-void
-pci_build_rom_resources(struct pci_dev* Pci_Dev) {
- u32 RomSaveArea, RomSizeBits;
- u64 RomSize = 0;
- struct resource* Resource = &Pci_Dev->resource[PCI_ROM_RESOURCE];
- PPCDBG(PPCDBG_BUSWALK, "\tpci_read_bar_Rom \n");
-
- pci_read_config_dword( Pci_Dev, PCI_ROM_ADDRESS, &RomSaveArea);
- pci_write_config_dword(Pci_Dev, PCI_ROM_ADDRESS, 0XFFFFFFFF);
- pci_read_config_dword( Pci_Dev, PCI_ROM_ADDRESS, &RomSizeBits);
- pci_write_config_dword(Pci_Dev, PCI_ROM_ADDRESS, RomSaveArea);
-
- if( (RomSizeBits&PCI_ROM_ADDRESS_ENABLE) == PCI_ROM_ADDRESS_ENABLE) {
- RomSize = ~(RomSizeBits) & PCI_ROM_ADDRESS_MASK;
- if(RomSize > 0) {
- Resource->name = Pci_Dev->name;
- Resource->flags = IORESOURCE_MEM | IORESOURCE_READONLY | IORESOURCE_PREFETCH;
- Resource->start = RomSaveArea;
- Resource->end = Resource->start + RomSize - 1;
- }
- }
-}
-/******************************************************************
- *
- * pci_read_bar_registers
- *
- * This function is the hook from the independant code to the arch
- * dependant code to set and read the BAR registers.
- *
- * Note: This is pSeries brand specific code.
- * In the future, this code will be setting the initial BAR
- * value and handing out the PBH memory space.
- ******************************************************************/
-int
-pci_read_bar_registers(struct pci_dev* Pci_Dev, int Count, int RomFlag) {
- u16 Pci_Command_Register_Save = 0;
- u16 Pci_Mask_Reg;
- /**************************************************************
- * If Io or Memory is enabled, disable while the BARs are being
- * changed to avoid any side affects.
- **************************************************************/
- if(( pci_read_config_word( Pci_Dev, PCI_COMMAND, &Pci_Command_Register_Save) != 0 ) ||
- (Pci_Command_Register_Save == (u16)0xFFFF) ) {
- printk("PCI: Device %s Read Command Failed.\n",Pci_Dev->slot_name);
- PPCDBG(PPCDBG_BUSWALK,"\tDevice %s Read Command Failed.\n",Pci_Dev->slot_name);
- return -1;
- }
- Pci_Mask_Reg = Pci_Command_Register_Save &(PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
- if( Pci_Mask_Reg != 0) {
- u16 ResetCmdReg = Pci_Command_Register_Save & (~Pci_Mask_Reg);
- pci_write_config_word( Pci_Dev, PCI_COMMAND, ResetCmdReg);
- }
- else {
- Pci_Command_Register_Save = 0;
- }
- /**************************************************************
- * Do the base BARS.
- **************************************************************/
- pci_build_bar_resources(Pci_Dev, Count);
-
- /**************************************************************
- * Rom Flag on, read ROM BARS.
- **************************************************************/
- if(RomFlag != 0) {
- pci_build_rom_resources(Pci_Dev);
- }
-
- /**************************************************************
- * If the Command Register was modifed, restore it.
- **************************************************************/
- if(Pci_Command_Register_Save != 0) {
- pci_write_config_word( Pci_Dev, PCI_COMMAND, Pci_Command_Register_Save);
- PPCDBG(PPCDBG_BUSWALK,"\tPCI_COMMAND Register Restored 0x%04X\n",
- Pci_Command_Register_Save);
- }
- return 0;
-}
/******************************************************************
* Find all PHBs in the system and initialize a set of data
@@ -432,7 +187,6 @@
struct resource *res;
unsigned int memno, rlen, i, index;
unsigned int *opprop;
-
PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n");
if(naca->interrupt_controller == IC_OPEN_PIC) {
@@ -449,6 +203,11 @@
return(-1);
}
+ if (find_type_devices("isa")) {
+ isa_io_limit = 0; /* allow all ISA ports down to zero. */
+ PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n");
+ }
+
index = 0;
/******************************************************************
@@ -476,10 +235,10 @@
range_stride = this_addr_count + root_addr_size_words + this_addr_size_words;
memno = 0;
- phb->io_base_phys = 0;
+ phb->io_base_phys = 0;
ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen);
- PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen);
+ PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen);
for(i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) {
/* Put the PCI addr part of the current element into a
@@ -518,21 +277,26 @@
res = NULL;
switch ((range.child_addr.a_hi >> 24) & 0x3) {
case 1: /* I/O space */
+ PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n");
phb->io_base_phys = range.parent_addr;
+ phb->io_base_virt = ioremap(phb->io_base_phys, range.size);
+ if (!isa_io_base)
+ isa_io_base = (unsigned long)phb->io_base_virt;
res = &phb->io_resource;
+ res->name = Pci_Node->full_name;
res->flags = IORESOURCE_IO;
- if (isa_io_base == 0) {
- isa_io_base = (unsigned long)
- ioremap(phb->io_base_phys, range.size);
- PPCDBG(PPCDBG_PHBINIT, "\tisa_io_base = 0x%lx\n", isa_io_base);
- }
+ res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
+ res->start += (unsigned long)phb->io_base_virt - isa_io_base;
+ res->end = res->start + range.size - 1;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
phb->pci_io_offset = range.parent_addr -
((((unsigned long)
range.child_addr.a_mid) << 32) |
(range.child_addr.a_lo));
PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset = 0x%lx\n",
phb->pci_io_offset);
-
break;
case 2: /* mem space */
PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n");
@@ -542,37 +306,32 @@
(range.child_addr.a_lo));
PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n",
phb->pci_mem_offset);
- res = &(phb->mem_resources[memno]);
- res->flags = IORESOURCE_MEM;
- ++memno;
+ if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) {
+ res = &(phb->mem_resources[memno]);
+ ++memno;
+ res->name = Pci_Node->full_name;
+ res->flags = IORESOURCE_MEM;
+ res->start = range.parent_addr;
+ res->end = range.parent_addr + range.size - 1;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+ }
break;
}
- if (res) {
- res->name = Pci_Node->full_name;
- res->start = range.parent_addr;
- res->end = range.parent_addr + range.size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
}
PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys = 0x%lx\n",
phb->io_base_phys);
PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n",
phb->pci_mem_offset);
- if(naca->interrupt_controller == IC_OPEN_PIC) {
- if(root_addr_size_words == 1) {
- openpic_setup_ISU(index, opprop[index+1]);
- } else {
- openpic_setup_ISU(index,
- ((unsigned long)opprop[(index+1)*2]) << 32 |
- opprop[(index+1)*2+1]);
- }
- }
-
+ if(naca->interrupt_controller == IC_OPEN_PIC) {
+ int addr = root_addr_size_words * (index + 2) - 1;
+ openpic_setup_ISU(index, opprop[addr]);
+ }
index++;
}
+ pci_devs_phb_init();
return 0; /*Success */
}
@@ -587,7 +346,8 @@
struct pci_controller *phb;
unsigned int *ui_ptr = NULL, len;
struct reg_property64 reg_struct;
- int *bus_range;
+ int *bus_range;
+ int *buid_vals;
PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name);
PPCDBG(PPCDBG_PHBINIT, "\tdev = 0x%lx\n", dev);
@@ -644,19 +404,25 @@
phb = pci_alloc_pci_controller("PHB SW",phb_type_speedwagon);
if(phb == NULL) return NULL;
- phb->cfg_addr = (volatile unsigned long *)
- ioremap(reg_struct.address + 0x140, PAGE_SIZE);
- phb->cfg_data = (char*)(phb->cfg_addr - 0x02); /* minus is correct */
- phb->phb_regs = (volatile unsigned long *)
- ioremap(reg_struct.address, PAGE_SIZE);
+ if (_machine == _MACH_pSeries) {
+ phb->cfg_addr = (volatile unsigned long *)
+ ioremap(reg_struct.address + 0x140, PAGE_SIZE);
+ phb->cfg_data = (char*)(phb->cfg_addr - 0x02); /* minus is correct */
+ phb->phb_regs = (volatile unsigned long *)
+ ioremap(reg_struct.address, PAGE_SIZE);
+ /* Speedwagon's register file is 1 MB in size. */
+ phb->chip_regs = ioremap(reg_struct.address & ~(0xfffffUL),
+ 0x100000);
+ PPCDBG(PPCDBG_PHBINIT, "\tmapping chip_regs from 0x%lx -> 0x%lx\n",
+ reg_struct.address & 0xfffff, phb->chip_regs);
+ } else {
+ phb->cfg_addr = NULL;
+ phb->cfg_data = NULL;
+ phb->phb_regs = NULL;
+ phb->chip_regs = NULL;
+ }
phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8;
-
- /* Speedwagon's register file is 1 MB in size. */
- phb->chip_regs = ioremap(reg_struct.address & ~(0xfffffUL),
- 0x100000);
- PPCDBG(PPCDBG_PHBINIT, "\tmapping chip_regs from 0x%lx -> 0x%lx\n",
- reg_struct.address & 0xfffff, phb->chip_regs);
/***************************************************************
* Trying to build a known just gets the code in trouble.
***************************************************************/
@@ -676,19 +442,26 @@
/***************************************************************
* Finished with the initialization
***************************************************************/
- phb->first_busno = bus_range[0];
- phb->last_busno = bus_range[1];
- //phb->first_busno = (phb->global_number <<8) + bus_range[0];
- //phb->last_busno = (phb->global_number <<8) + bus_range[1];
+ // phb->first_busno = bus_range[0];
+ // phb->last_busno = bus_range[1];
+ phb->first_busno = (phb->global_number <<8) + bus_range[0];
+ phb->last_busno = (phb->global_number <<8) + bus_range[1];
phb->arch_data = dev;
- if( Pci_Large_Bus_System == 0 ) phb->ops = &rtas_pci_ops;
- else phb->ops = &rtas64_pci_ops;
+ phb->ops = &rtas_pci_ops;
+
+ buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len);
+ if (buid_vals == NULL || len < 2 * sizeof(int)) {
+ phb->buid = 0;
+ } else {
+ phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |
+ (((unsigned long)buid_vals[1]) & 0xffffffff);
+ }
/***************************************************************
* Build tce table for phb
***************************************************************/
- phb_tce_table_init(phb);
+ /* DRENG Obsolete phb_tce_table_init(phb); */
/* Dump PHB information for Debug */
PPCDBGCALL(PPCDBG_PHBINIT,dumpPci_Controller(phb) );
@@ -699,8 +472,7 @@
void
fixup_resources(struct pci_dev *dev) {
int i;
- unsigned long size;
- struct pci_controller* phb = (struct pci_controller *)dev->sysdata;
+ struct pci_controller* phb = PCI_GET_PHB_PTR(dev);
PPCDBG(PPCDBG_PHBINIT, "fixup_resources:\n");
PPCDBG(PPCDBG_PHBINIT, "\tphb = 0x%016LX\n", phb);
@@ -712,7 +484,7 @@
if(phb == NULL) return;
- for (i = 0; i < 6; ++i) {
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) {
PPCDBG(PPCDBG_PHBINIT, "\tdevice %x.%x[%d] (flags %x) [%lx..%lx]\n",
dev->bus->number, dev->devfn, i,
dev->resource[i].flags,
@@ -724,20 +496,20 @@
}
if (dev->resource[i].flags & IORESOURCE_IO) {
- dev->resource[i].start += phb->pci_io_offset;
- dev->resource[i].end += phb->pci_io_offset;
- size = dev->resource[i].end - dev->resource[i].start;
- dev->resource[i].start =
- ((unsigned long) ioremap(dev->resource[i].start,
- size)) - isa_io_base;
- dev->resource[i].end = dev->resource[i].start + size;
-
+ unsigned long offset = (unsigned long) phb->io_base_virt - isa_io_base;
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx (%lx) .. %lx (%lx)]\n",
- dev->resource[i].start, ___pa(dev->resource[i].start + isa_io_base),
- dev->resource[i].end, ___pa(dev->resource[i].end + isa_io_base));
+ dev->resource[i].start, 0/*___pa(dev->resource[i].start + isa_io_base)*/,
+ dev->resource[i].end, 0/* ___pa(dev->resource[i].end + isa_io_base)*/);
} else if (dev->resource[i].flags & IORESOURCE_MEM) {
- dev->resource[i].start += phb->pci_mem_offset;
- dev->resource[i].end += phb->pci_mem_offset;
+ if (dev->resource[i].start == 0) {
+ /* Bogus. Probably an unused bridge. */
+ dev->resource[i].end = 0;
+ } else {
+ dev->resource[i].start += phb->pci_mem_offset;
+ dev->resource[i].end += phb->pci_mem_offset;
+ }
PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx..%lx]\n",
dev->resource[i].start, dev->resource[i].end);
@@ -760,6 +532,7 @@
pci_assign_all_busses = 0;
pci_for_each_dev(dev) {
+ pci_read_irq_line(dev);
PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Dev(dev) );
}
@@ -787,89 +560,6 @@
return NULL;
}
-/***********************************************************************
- *
- * scan_OF_childs_for_device
- *
- * The function is a helper function for the pci_device_to_OF_node. It
- * walks down the passed node, looking for a node entry that matches the
- * requested bus and device function. NOTE: If a bridge is found in the
- * scan, it will recurse this the function to to scan that bridge looking
- * for a match. If none found, the return will continue down the orginal
- * tree.
- *
- * Return:
- * Node matching the bus and devfn passed or NULL.
- ***********************************************************************/
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
-{
- struct device_node* CurrentNode; /* Current node being scanned. */
- struct device_node* DeviceNode; /* Node of Device */
- u32* Register; /* Pointer to Register Array */
- u32* Class_Code; /* Pointer to ClassCode property */
- CurrentNode = node;
- DeviceNode = NULL;
- while(CurrentNode != NULL && DeviceNode == NULL) {
- u32 IoaAddress;
- u8 IoaBus, IoaDevFn;
-
- Register = (unsigned int *) get_property(CurrentNode,"reg", 0);
- if(Register != NULL) {
- /* 1st register entry is the Ioa Address = 00BBSS00 */
- IoaAddress = Register[0];
- IoaBus = (IoaAddress & 0x00FF0000) >> 16;
- IoaDevFn = (IoaAddress & 0x0000FF00) >> 8;
- if( (IoaBus == bus) && (IoaDevFn == dev_fn ) ) {
- DeviceNode = CurrentNode;
- return DeviceNode;
- }
- }
- /***************************************************************
- * check for a bridge, if so scan the branch of the tree for a match.
- ***************************************************************/
- Class_Code = (unsigned int*) get_property(CurrentNode,"class-code", 0);
- if(Class_Code != NULL) {
- u32 PciClassCode = ((*Class_Code)&0x00FFFF00)>>8;
-
- if(( PciClassCode == PCI_CLASS_BRIDGE_PCI) ||
- ( PciClassCode == PCI_CLASS_BRIDGE_CARDBUS) ) {
-
- PPCDBG(PPCDBG_BUSWALK,"\tScan OF behind bridge\n");
- DeviceNode = scan_OF_childs_for_device(CurrentNode->child, bus, dev_fn);
- if(DeviceNode != NULL) {
- return DeviceNode;
- }
- }
- }
- /***************************************************************
- * Try the next node.
- ***************************************************************/
- CurrentNode = CurrentNode->sibling;
- }
- return NULL;
-}
-/***********************************************************************
- * pci_device_to_OF_node
- *
- * This function Finds the Open Firmware node for the passed in pci_dev.
- * It starts at the Phb's node for the device and calls the
- * scan_OF_childs_for_device to looking for the matching entry.
- *
- * Return:
- * Node matching the device or NULL if it was not found.
- ***********************************************************************/
-struct device_node*
-pci_device_to_OF_node(struct pci_dev* Pci_Dev)
-{
- struct pci_controller* Phb;
- struct device_node* PhbNode;
- struct device_node* DeviceNode;
- Phb = PCI_GET_PHB_PTR(Pci_Dev);
- PhbNode = (struct device_node *) Phb->arch_data;
- DeviceNode = scan_OF_childs_for_device(PhbNode->child, PCI_GET_BUS_NUMBER(Pci_Dev), Pci_Dev->devfn);
- return DeviceNode;
-}
/***********************************************************************
* find_floppy(void)
*
@@ -912,18 +602,21 @@
pSeries_pcibios_init(void) {
PPCDBG(PPCDBG_PHBINIT, "\tppc64_pcibios_init Entry.\n");
- if(get_property(find_path_device("/rtas"),"read-pc-config",NULL) != NULL) {
- PPCDBG(PPCDBG_PHBINIT, "\tFound: read-pc-config\n");
- }
- else PPCDBG(PPCDBG_PHBINIT, "\tNOT Found: read-pc-config\n");
-
-
- if(get_property(find_path_device("/rtas"),"ibm,read-pc-config",NULL) != NULL) {
- PPCDBG(PPCDBG_PHBINIT, "\tFound: ibm,read-pc-config\n");
- Pci_Set_IOA_Address = 1;
- }
if(get_property(find_path_device("/rtas"),"ibm,fw-phb-id",NULL) != NULL) {
PPCDBG(PPCDBG_PHBINIT, "\tFound: ibm,fw-phb-id\n");
Pci_Large_Bus_System = 1;
}
+}
+
+/*
+ * This is called very early before the page table is setup.
+ */
+void
+pSeries_pcibios_init_early(void) {
+ ppc_md.pcibios_read_config_byte = rtas_read_config_byte;
+ ppc_md.pcibios_read_config_word = rtas_read_config_word;
+ ppc_md.pcibios_read_config_dword = rtas_read_config_dword;
+ ppc_md.pcibios_write_config_byte = rtas_write_config_byte;
+ ppc_md.pcibios_write_config_word = rtas_write_config_word;
+ ppc_md.pcibios_write_config_dword = rtas_write_config_dword;
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pacaData.c linuxppc64_2_4/arch/ppc64/kernel/pacaData.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/pacaData.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/pacaData.c Thu Sep 13 11:54:36 2001
@@ -31,49 +31,35 @@
* processor (not thread).
*/
#define PACAINITDATA(number,start,lpq,asrr,asrv) \
-{ (struct ItLpPaca *)(((char *)(&xPaca[number]))+offsetof(struct Paca, xLpPaca)), \
- (struct ItLpRegSave *)(((char *)(&xPaca[number]))+offsetof(struct Paca, xRegSav)), \
- 0, /* Current */ \
- 0, /* R21 Save */ \
- 0, /* R22 Save */ \
- 0, /* Kernel stack addr save */ \
- (number), /* Paca Index */ \
- 0, /* HW Proc Number */ \
- 0, /* CCR Save */ \
- 0, /* MSR Save */ \
- 0, /* LR Save */ \
- 0, /* Pointer to thread */ \
- {(asrr), /* Real pointer to segment table */ \
- (asrv), /* Virt pointer to segment table */ \
- REGION_COUNT-1}, /* Round robin index */ \
- {0,0,0,0,0,0,0,0},/* Segment cache */ \
- 0, /* Kernel TOC address */ \
- 0, /* R1 Save */ \
- (lpq), /* &xItLpQueue, */ \
- {0,0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, SPIN_LOCK_UNLOCKED, 0}, /*xRtas */ \
- (start), /* Processor start */ \
- {0,0,0}, /* Resv */ \
- 0, /* Default Decrementer */ \
- 0, /* next_jiffy_update_tb */ \
- {0,0,0,0,0,0,0,0,0,0,0,0}, /* Resv */ \
- { /* LpPaca */ \
- xDesc: 0xd397d781, /* "LpPa" */ \
- xSize: sizeof(struct ItLpPaca), /* */ \
- xFPRegsInUse: 1, \
- xDynProcStatus: 2, \
- xEndOfQuantum: 0xffffffffffffffff /* */ \
- }, \
- { /* LpRegSave */ \
- 0xd397d9e2, /* "LpRS" */ \
- sizeof(struct ItLpRegSave) /* */ \
- }, \
- 0, /* pvr */ \
- 0, /* pgd_cache */ \
- 0, /* pmd_cache */ \
- 0, /* pte_cache */ \
- 0, /* pgtable_cache_sz */ \
- 0, /* prof_multiplier */ \
- 0 /* prof_counter */ \
+{ \
+ xLpPacaPtr: &xPaca[number].xLpPaca, \
+ xLpRegSavePtr: &xPaca[number].xRegSav, \
+ xPacaIndex: (number), /* Paca Index */ \
+ default_decr: 0x00ff0000, /* Initial Decr */ \
+ xStab_data: { \
+ real: (asrr), /* Real pointer to segment table */ \
+ virt: (asrv), /* Virt pointer to segment table */ \
+ next_round_robin: 1 /* Round robin index */ \
+ }, \
+ lpQueuePtr: (lpq), /* &xItLpQueue, */ \
+ xRtas: { \
+ lock: SPIN_LOCK_UNLOCKED \
+ }, \
+ xProcStart: (start), /* Processor start */ \
+ xLpPaca: { \
+ xDesc: 0xd397d781, /* "LpPa" */ \
+ xSize: sizeof(struct ItLpPaca), \
+ xFPRegsInUse: 1, \
+ xDynProcStatus: 2, \
+ xDecrVal: 0x00ff0000, \
+ xEndOfQuantum: 0xffffffffffffffff \
+ }, \
+ xRegSav: { \
+ xDesc: 0xd397d9e2, /* "LpRS" */ \
+ xSize: sizeof(struct ItLpRegSave) \
+ }, \
+ exception_sp: \
+ &xPaca[number].exception_stack[N_EXC_STACK*EXC_FRAME_SIZE], \
}
struct Paca xPaca[maxPacas] __page_aligned = {
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pci.c linuxppc64_2_4/arch/ppc64/kernel/pci.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/pci.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/pci.c Thu Sep 6 15:59:33 2001
@@ -34,6 +34,17 @@
#include "pci.h"
+/* isa_io_limit -- only I/O ports above this addr are recognized by inb/outb.
+ * We fake failure below this limit without trashing the system.
+ * This is zero when an ISA bus exists, else PAGE_SIZE.
+ */
+unsigned long isa_io_limit = PAGE_SIZE;
+/* isa_io_base -- the base address from which io bars are offsets.
+ * This is the lowest I/O base address (so bar values are always positive),
+ * and it *must* be the start of ISA space if an ISA bus exists because
+ * ISA drivers use hard coded offsets. If no ISA bus exists a dummy
+ * page is mapped and isa_io_limit prevents access to it.
+ */
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
unsigned long pci_dram_offset = 0;
@@ -41,7 +52,8 @@
/******************************************************************
* Forward declare of prototypes
******************************************************************/
-void pcibios_fixup_resources(struct pci_dev* dev);
+static void pcibios_fixup_resources(struct pci_dev* dev);
+static void fixup_broken_pcnet32(struct pci_dev* dev);
void fixup_resources(struct pci_dev* dev); /* In brand pci code */
struct pci_dev *find_floppy(void);
@@ -67,10 +79,20 @@
struct pci_dev *ppc64_floppy_dev = NULL;
struct pci_fixup pcibios_fixups[] = {
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
{ 0 }
};
+static void fixup_broken_pcnet32(struct pci_dev* dev)
+{
+ if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
+ dev->vendor = PCI_VENDOR_ID_AMD;
+ pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+ pci_name_device(dev);
+ }
+}
+
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges)
{
@@ -83,7 +105,7 @@
{
u32 new, check;
int reg;
- struct pci_controller* hose = dev->sysdata;
+ struct pci_controller* hose = PCI_GET_PHB_PTR(dev);
new = res->start;
if (hose && res->flags & IORESOURCE_MEM)
@@ -186,22 +208,29 @@
{
struct list_head *ln;
struct pci_bus *bus;
- struct pci_dev *dev;
- int idx;
- struct resource *r, *pr;
+ int i;
+ struct resource *res, *pr;
/* Depth-First Search on bus tree */
for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
bus = pci_bus_b(ln);
- if ((dev = bus->self)) {
- for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
- r = &dev->resource[idx];
- if (!r->start)
- continue;
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0)
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
- }
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL || !res->flags)
+ continue;
+ if (bus->parent == NULL)
+ pr = (res->flags & IORESOURCE_IO)?
+ &ioport_resource: &iomem_resource;
+ else
+ pr = pci_find_parent_resource(bus->self, res);
+
+ if (pr == res)
+ continue; /* transparent bus or undefined */
+ if (pr && request_resource(pr, res) == 0)
+ continue;
+ printk(KERN_ERR "PCI: Cannot allocate resource region "
+ "%d of PCI bridge %x\n", i, bus->number);
+ printk(KERN_ERR "PCI: resource is %lx..%lx (%lx), parent %p\n",
+ res->start, res->end, res->flags, pr);
}
pcibios_allocate_bus_resources(&bus->children);
}
@@ -398,14 +427,13 @@
/* Scan all of the recorded PCI controllers. */
for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
hose->last_busno = 0xff;
- bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
+ bus = pci_scan_bus(hose->first_busno, hose->ops, hose->arch_data);
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;
-
/* Call machine dependant fixup */
if (ppc_md.pcibios_fixup) {
@@ -417,21 +445,13 @@
/* Allocate and assign resources */
pcibios_allocate_bus_resources(&pci_root_buses);
- if(naca->io_subsystem == IOS_OPEN_PIC) {
- pcibios_allocate_resources(0); // DRENG Condor removed. This will have to be reviewed!!!
- }
- if(naca->io_subsystem == IOS_OPEN_PIC) {
- pcibios_allocate_resources(1); // DRENG Condor removed. This will have to be reviewed!!!
- }
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
pcibios_assign_resources();
- /*
- * Set up TCE tables for each PHB.
- */
- for (hose = hose_head; hose; hose = hose->next) {
- create_pci_bus_tce_table(hose->global_number,
- (unsigned long)hose);
- }
+ pci_fix_bus_sysdata();
+
+ create_tce_tables();
ppc64_floppy_dev = find_floppy();
@@ -454,7 +474,53 @@
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
- pci_read_bridge_bases(bus);
+ struct pci_controller *phb = PCI_GET_PHB_PTR(bus);
+ struct resource *res;
+ unsigned long io_offset;
+ int i;
+
+ io_offset = (unsigned long)phb->io_base_virt - isa_io_base;
+
+ if (bus->parent == NULL) {
+ /* This is a host bridge - fill in its resources */
+ phb->bus = bus;
+ bus->resource[0] = res = &phb->io_resource;
+ if (!res->flags)
+ BUG(); /* No I/O resource for this PHB? */
+
+ for (i = 0; i < 3; ++i) {
+ res = &phb->mem_resources[i];
+ if (!res->flags) {
+ if (i == 0)
+ BUG(); /* No memory resource for this PHB? */
+ }
+ bus->resource[i+1] = res;
+ }
+ } else {
+ /* This is a subordinate bridge */
+ pci_read_bridge_bases(bus);
+
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL)
+ continue;
+ if (!res->flags)
+ continue;
+ if (res == pci_find_parent_resource(bus->self, res)) {
+ /* Transparent resource -- don't try to "fix" it. */
+ continue;
+ }
+ if (res->flags & IORESOURCE_IO) {
+ res->start += io_offset;
+ res->end += io_offset;
+ } else if (phb->pci_mem_offset
+ && (res->flags & IORESOURCE_MEM)) {
+ if (res->start < phb->pci_mem_offset) {
+ res->start += phb->pci_mem_offset;
+ res->end += phb->pci_mem_offset;
+ }
+ }
+ }
+ }
if ( ppc_md.pcibios_fixup_bus )
ppc_md.pcibios_fixup_bus(bus);
@@ -546,7 +612,7 @@
*/
int pci_controller_num(struct pci_dev *dev)
{
- struct pci_controller *hose = (struct pci_controller *) dev->sysdata;
+ struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
return hose->global_number;
}
@@ -572,7 +638,7 @@
__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
- struct pci_controller *hose = (struct pci_controller *) dev->sysdata;
+ struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long io_offset = 0;
int i, res_bit;
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pci.h linuxppc64_2_4/arch/ppc64/kernel/pci.h
--- linux-2.4.9-ac10/arch/ppc64/kernel/pci.h Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/pci.h Tue Sep 11 07:12:11 2001
@@ -9,8 +9,6 @@
#ifndef __PPC_KERNEL_PCI_H__
#define __PPC_KERNEL_PCI_H__
-/* Include these to prevent strange compile warnings if user forgets
- * to include them in their .c file. */
#include
#include
@@ -29,27 +27,58 @@
extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type);
extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
+extern struct pci_controller* hose_head;
+extern struct pci_controller** hose_tail;
+
/*******************************************************************
* Platform functions that are brand specific implementation.
*******************************************************************/
extern unsigned long find_and_init_phbs(void);
-extern int pci_read_irq_line(struct pci_dev* PciDev);
-extern int pci_read_bar_registers(struct pci_dev* PciDev, int Count, int RomFlag);
-
extern void fixup_resources(struct pci_dev *dev);
extern void ppc64_pcibios_init(void);
extern int pci_reset_device(struct pci_dev*);
extern int pci_get_location(struct pci_dev*, char*, int);
-extern struct pci_dev* find_floppy(void);
extern struct pci_dev *ppc64_floppy_dev;
+
+/*******************************************************************
+ * PCI device_node operations
+ *******************************************************************/
+struct device_node;
+typedef void *(*traverse_func)(struct device_node *me, void *data);
+void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data);
+void *traverse_all_pci_devices(traverse_func pre);
+
+void pci_devs_phb_init(void);
+void pci_fix_bus_sysdata(void);
+struct device_node *fetch_dev_dn(struct pci_dev *dev);
+
+void iSeries_pcibios_init_early(void);
+void pSeries_pcibios_init_early(void);
+
+/* Get a device_node from a pci_dev. This code must be fast except in the case
+ * where the sysdata is incorrect and needs to be fixed up (hopefully just once)
+ */
+static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
+{
+ struct device_node *dn = (struct device_node *)(dev->sysdata);
+ if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
+ return dn; /* fast path. sysdata is good */
+ else
+ return fetch_dev_dn(dev);
+}
+/* Use this macro after the PCI bus walk for max performance when it
+ * is known that sysdata is correct.
+ */
+#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
+
+
/*******************************************************************
* Platform configuration flags.. (Live in pci.c)
*******************************************************************/
extern int Pci_Large_Bus_System; /* System has > 256 buses */
-extern int Pci_Set_IOA_Address; /* Set IOA BARs from OF */
extern int Pci_Manage_Phb_Space; /* Manage Phb Space for IOAs*/
/*******************************************************************
@@ -58,9 +87,9 @@
* PCI_GET_PHB_NUMBER(struct pci_dev*) returns the Phb number.
* PCI_GET_BUS_NUMBER(struct pci_dev*) returns the bus number.
*******************************************************************/
-#define PCI_GET_PHB_PTR(PCIDEV) ((struct pci_controller*)##PCIDEV##->sysdata)
-#define PCI_GET_PHB_NUMBER(PCIDEV) ((##PCIDEV##->bus->number&0x00FFFF00)>>8)
-#define PCI_GET_BUS_NUMBER(PCIDEV) ( ##PCIDEV##->bus->number&0x0000FF)
+#define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb)
+#define PCI_GET_PHB_NUMBER(dev) (((dev)->bus->number&0x00FFFF00)>>8)
+#define PCI_GET_BUS_NUMBER(dev) ((dev)->bus->number&0x0000FF)
/*******************************************************************
* Pci Flight Recorder support.
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pci_dma.c linuxppc64_2_4/arch/ppc64/kernel/pci_dma.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/pci_dma.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/pci_dma.c Thu Sep 13 08:06:56 2001
@@ -39,6 +39,10 @@
#include
#include
+#include
+
+#include "pci.h"
+
#define DEBUG_TCE 1
/* Initialize so this guy does not end up in the BSS section.
@@ -47,6 +51,9 @@
*/
extern struct _of_tce_table of_tce_table[];
+extern struct pci_controller* hose_head;
+extern struct pci_controller** hose_tail;
+
struct TceTable virtBusTceTable; /* Tce table for virtual bus */
struct TceTable * tceTables[256]; /* Tce tables for 256 busses
@@ -62,9 +69,9 @@
static long alloc_tce_range_nolock( struct TceTable *,
unsigned order );
/* frees a contiguous range of tces (power-of-2 size) */
-static void free_tce_range( struct TceTable *,
- long tcenum,
- unsigned order );
+void free_tce_range( struct TceTable *,
+ long tcenum,
+ unsigned order );
/* frees a contiguous rnage of tces (power-of-2 size)
* assumes lock already held
*/
@@ -78,10 +85,6 @@
unsigned numPages,
int tceType,
int direction );
-static void free_tces( struct TceTable *,
- dma_addr_t tce,
- unsigned order,
- unsigned numPages );
static long test_tce_range( struct TceTable *,
long tcenum,
unsigned order );
@@ -99,84 +102,109 @@
int tceType,
int direction );
-static void getTceTableParms( struct pci_controller *phb,
- struct TceTable *tce_table_parms );
+static void getTceTableParmsPSeries( struct pci_controller *phb,
+ struct TceTable *tce_table_parms );
-static unsigned long setTce( unsigned long base,
- unsigned long tce_num,
- unsigned long tce_data);
-
static long resv_tce_range_top_level( struct TceTable *tbl,
unsigned long dma_addr,
unsigned size );
+void create_pci_bus_tce_table( unsigned long token );
+
u8 iSeries_Get_Bus( struct pci_dev * dv )
{
return 0;
}
-/*
- * Given a pci device, return which tce table is assigned to it.
- */
-unsigned long get_tce_table_index( struct pci_dev *dev) {
- unsigned long index =
- ((struct pci_controller *)dev->sysdata)->global_number;
- PPCDBG(PPCDBG_TCE, "get_tce_table_index:\n");
- PPCDBG(PPCDBG_TCE, "\tdev = 0x%lx, index = 0x%lx\n", dev, index);
- return(index);
+struct TceTable *get_tce_table(struct pci_dev *dev) {
+ unsigned long bus;
+
+ switch(_machine) {
+ case _MACH_iSeries:
+ /* If no dev, assume virtual bus */
+ if(dev) bus = dev->bus->number;
+ else bus = 255;
+ return(tceTables[bus]);
+ default:
+ return PCI_GET_DN(dev)->tce_table;
+ }
+ return(NULL);
}
-static unsigned __inline__ count_leading_zeros32( unsigned long x )
+static unsigned long __inline__ count_leading_zeros64( unsigned long x )
{
- unsigned lz;
- asm("cntlzw %0,%1" : "=r"(lz) : "r"(x));
+ unsigned long lz;
+ asm("cntlzd %0,%1" : "=r"(lz) : "r"(x));
return lz;
}
-static void __inline__ build_tce( struct TceTable * tbl, long tcenum,
- unsigned long uaddr, int tceType, int direction )
+static void tce_build_iSeries(struct TceTable *tbl, long tcenum,
+ unsigned long uaddr, int tceType, int direction )
{
u64 setTceRc;
union Tce tce;
PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr);
+ PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n",
+ tcenum, tbl, tbl->index);
+
tce.wholeTce = 0;
tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT;
+
/* If for virtual bus */
if ( tceType == TCE_VB ) {
tce.tceBits.valid = 1;
tce.tceBits.allIo = 1;
if ( direction != PCI_DMA_TODEVICE )
tce.tceBits.readWrite = 1;
- }
- /* If for PCI bus */
- else {
+ } else {
+ /* If for PCI bus */
tce.tceBits.readWrite = 1; // Read allowed
if ( direction != PCI_DMA_TODEVICE )
tce.tceBits.pciWrite = 1;
}
-#ifdef CONFIG_PPC_ISERIES
- setTceRc = HvCallXm_setTce( (u64)tbl->index, (u64)tcenum, tce.wholeTce );
-#else
- setTceRc = setTce( (u64)tbl->base, (u64)tcenum, tce.wholeTce );
-#endif
+ setTceRc = HvCallXm_setTce((u64)tbl->index,
+ (u64)tcenum,
+ tce.wholeTce );
- if ( setTceRc ) {
- PPCDBG(PPCDBG_TCE, "build_tce: HvCallXm_setTce failed, rc=%ld, index=%ld, tcenum=%0lx, tce=%016lx\n",
- (u64)tbl->index, (u64)tcenum, tce.wholeTce );
+ if(setTceRc) {
+ PPCDBG(PPCDBG_TCE, "setTce failed. rc=%ld\n", setTceRc);
+ PPCDBG(PPCDBG_TCE, "\tindex = 0x%lx\n", (u64)tbl->index);
+ PPCDBG(PPCDBG_TCE, "\ttce num = 0x%lx\n", (u64)tcenum);
+ PPCDBG(PPCDBG_TCE, "\ttce val = 0x%lx\n", tce.wholeTce );
}
-
}
+static void tce_build_pSeries(struct TceTable *tbl, long tcenum,
+ unsigned long uaddr, int tceType, int direction )
+{
+ union Tce tce;
+ union Tce *tce_addr;
+
+ PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr);
+ PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n",
+ tcenum, tbl, tbl->index);
+ tce.wholeTce = 0;
+ tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT;
+
+ tce.tceBits.readWrite = 1; // Read allowed
+ if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1;
+
+ tce_addr = ((union Tce *)tbl->base) + tcenum;
+ *tce_addr = (union Tce)tce.wholeTce;
+
+ /* Make sure the update is visible to hardware. */
+ __asm__ __volatile__ ("sync" : : : "memory");
+}
/*
* Build a TceTable structure. This contains a multi-level bit map which
* is used to manage allocation of the tce space.
*/
-struct TceTable * build_tce_table( struct TceTable * tbl )
+static struct TceTable *build_tce_table( struct TceTable * tbl )
{
unsigned long bits, bytes, totalBytes;
unsigned long numBits[NUM_TCE_LEVELS], numBytes[NUM_TCE_LEVELS];
@@ -199,7 +227,7 @@
numBits[i] = bits;
numBytes[i] = bytes;
bits /= 2;
- totalBytes += bytes;
+ totalBytes += ((bytes + 7) / 8) * 8;
}
PPCDBG(PPCDBG_TCE, "build_tce_table: totalBytes=%ld\n", totalBytes );
@@ -259,9 +287,7 @@
}
}
-
return tbl;
-
}
static long alloc_tce_range( struct TceTable *tbl, unsigned order )
@@ -288,7 +314,7 @@
unsigned long numBits, numBytes;
unsigned long i, bit, block, mask;
long tcenum;
- unsigned char * map;
+ u64 * map;
/* If the order (power of 2 size) requested is larger than our
* biggest, indicate failure
@@ -301,23 +327,23 @@
numBits = tbl->mlbm.level[order].numBits;
numBytes = tbl->mlbm.level[order].numBytes;
- map = tbl->mlbm.level[order].map;
+ map = (u64 *)tbl->mlbm.level[order].map;
/* Initialize return value to -1 (failure) */
tcenum = -1;
/* Loop through the bytes of the bitmap */
- for (i=0; i> bit);
+ mask = 0xffffffffffffffffLL ^ (0x8000000000000000LL >> bit);
*map &= mask;
/* compute the index into our tce table for
* the first tce in the block
@@ -357,7 +383,7 @@
}
-static void free_tce_range( struct TceTable *tbl, long tcenum, unsigned order )
+void free_tce_range( struct TceTable *tbl, long tcenum, unsigned order )
{
unsigned long flags;
@@ -372,7 +398,7 @@
}
-static void free_tce_range_nolock( struct TceTable *tbl, long tcenum, unsigned order )
+static void free_tce_range_nolock( struct TceTable *tbl, long tcenum, unsigned order )
{
unsigned long block;
unsigned byte, bit, mask, b;
@@ -415,10 +441,12 @@
* If this is the highest level we can't buddy up
* If this level has an odd number of bits and
* we are freeing the last block we can't buddy up
+ * Don't buddy up if it's in the first 1/4 of the level
*/
if ( ( order < tbl->mlbm.maxLevel ) &&
( ( 0 == ( tbl->mlbm.level[order].numBits & 1 ) ) ||
- ( block < tbl->mlbm.level[order].numBits-1 ) ) ) {
+ ( block < tbl->mlbm.level[order].numBits-1 ) ) &&
+ ( block > (tbl->mlbm.level[order].numBits/4) ) ) {
/* See if we can buddy up the block we just freed */
bit &= 6; /* get to the first of the buddy bits */
@@ -485,7 +513,8 @@
retTce = tcenum << PAGE_SHIFT; /* Set the return dma address */
/* Setup a tce for each page */
for (i=0; istartOffset;
if ( tcenum > maxTcenum ) {
- PPCDBG(PPCDBG_TCE, "free_tces: tcenum > maxTcenum, tcenum = %ld, maxTcenum = %ld\n",
- tcenum, maxTcenum );
- PPCDBG(PPCDBG_TCE, "free_tces: TCE Table at %16lx\n", (unsigned long)tbl );
- PPCDBG(PPCDBG_TCE, "free_tces: bus# %lu\n", (unsigned long)tbl->busNumber );
- PPCDBG(PPCDBG_TCE, "free_tces: size %lu\n", (unsigned long)tbl->size );
- PPCDBG(PPCDBG_TCE, "free_tces: startOff %lu\n", (unsigned long)tbl->startOffset );
- PPCDBG(PPCDBG_TCE, "free_tces: index %lu\n", (unsigned long)tbl->index );
+ PPCDBG(PPCDBG_TCE, "free_tces: tcenum > maxTcenum\n");
+ PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx\n", tcenum);
+ PPCDBG(PPCDBG_TCE, "\tmaxTcenum = 0x%lx\n", maxTcenum);
+ PPCDBG(PPCDBG_TCE, "\tTCE Table = 0x%lx\n", (u64)tbl);
+ PPCDBG(PPCDBG_TCE, "\tbus# = 0x%lx\n",
+ (u64)tbl->busNumber );
+ PPCDBG(PPCDBG_TCE, "\tsize = 0x%lx\n", (u64)tbl->size);
+ PPCDBG(PPCDBG_TCE, "\tstartOff = 0x%lx\n",
+ (u64)tbl->startOffset );
+ PPCDBG(PPCDBG_TCE, "\tindex = 0x%lx\n", (u64)tbl->index);
return;
}
@@ -522,22 +555,68 @@
for (i=0; iindex, (u64)tcenum, tce.wholeTce );
-#else
- setTceRc = setTce( (u64)tbl->base, (u64)tcenum, tce.wholeTce );
-#endif
+ setTceRc = HvCallXm_setTce((u64)tbl->index,
+ (u64)tcenum,
+ tce.wholeTce );
if ( setTceRc ) {
- PPCDBG(PPCDBG_TCE, "free_tces: HvCallXm_setTce failed, rc=%ld, index=%ld, tcenum=%0lx, tce=%016lx\n",
- (u64)tbl->index, (u64)tcenum, tce.wholeTce );
+ PPCDBG(PPCDBG_TCE, "tce_free: setTce failed\n");
+ PPCDBG(PPCDBG_TCE, "\trc = 0x%lx\n", setTceRc);
+ PPCDBG(PPCDBG_TCE, "\tindex = 0x%lx\n",
+ (u64)tbl->index);
+ PPCDBG(PPCDBG_TCE, "\ttce num = 0x%lx\n", (u64)tcenum);
+ PPCDBG(PPCDBG_TCE, "\ttce val = 0x%lx\n",
+ tce.wholeTce );
}
++tcenum;
}
free_tce_range( tbl, freeTce, order );
+}
+
+static void tce_free_pSeries(struct TceTable *tbl, dma_addr_t dma_addr,
+ unsigned order, unsigned numPages)
+{
+ long tcenum, freeTce, maxTcenum;
+ unsigned i;
+ union Tce tce;
+ union Tce *tce_addr;
+
+ maxTcenum = (tbl->size * (PAGE_SIZE / sizeof(union Tce))) - 1;
+
+ tcenum = dma_addr >> PAGE_SHIFT;
+ tcenum -= tbl->startOffset;
+
+ if ( tcenum > maxTcenum ) {
+ PPCDBG(PPCDBG_TCE, "free_tces: tcenum > maxTcenum\n");
+ PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx\n", tcenum);
+ PPCDBG(PPCDBG_TCE, "\tmaxTcenum = 0x%lx\n", maxTcenum);
+ PPCDBG(PPCDBG_TCE, "\tTCE Table = 0x%lx\n", (u64)tbl);
+ PPCDBG(PPCDBG_TCE, "\tbus# = 0x%lx\n",
+ (u64)tbl->busNumber );
+ PPCDBG(PPCDBG_TCE, "\tsize = 0x%lx\n", (u64)tbl->size);
+ PPCDBG(PPCDBG_TCE, "\tstartOff = 0x%lx\n",
+ (u64)tbl->startOffset );
+ PPCDBG(PPCDBG_TCE, "\tindex = 0x%lx\n", (u64)tbl->index);
+ return;
+ }
+
+ freeTce = tcenum;
+
+ for (i=0; ibase) + tcenum;
+ *tce_addr = (union Tce)tce.wholeTce;
+
+ ++tcenum;
+ }
+
+ /* Make sure the update is visible to hardware. */
+ __asm__ __volatile__ ("sync" : : : "memory");
+ free_tce_range( tbl, freeTce, order );
}
void __init create_virtual_bus_tce_table(void)
@@ -572,67 +651,93 @@
PPCDBG(PPCDBG_TCE, "Virtual Bus TCE table failed.\n");
}
-void create_pci_bus_tce_table( unsigned long busNumber,
- unsigned long token )
-{
- struct TceTable * t;
+void create_tce_tables(void) {
+ struct pci_controller *hose;
+ struct pci_dev *dev;
+ struct device_node *dn, *mydn;
+
+ if(_machine == _MACH_pSeries) {
+ for (hose = hose_head; hose; hose = hose->next) {
+ create_pci_bus_tce_table((unsigned long)hose);
+ }
+ }
+
+ /* Now copy the tce_table ptr from the bus devices down to every
+ * pci device_node. This means get_tce_table() won't need to search
+ * up the device tree to find it.
+ */
+ pci_for_each_dev(dev) {
+ mydn = dn = PCI_GET_DN(dev);
+ while (dn && dn->tce_table == NULL)
+ dn = dn->parent;
+ if (dn) {
+ mydn->tce_table = dn->tce_table;
+ } else {
+ printk("create_tce_tables could not locate a tce table for a device!\n");
+ BUG();
+ }
+ }
+}
+
+/*
+ * iSeries token = busNumber
+ * pSeries token = pci_controller*
+ */
+void create_pci_bus_tce_table( unsigned long token ) {
+ struct TceTable * builtTceTable;
struct TceTable * newTceTable;
struct TceTableManagerCB pciBusTceTableParms;
-#ifdef CONFIG_PPC_ISERIES
u64 parmsPtr;
-#endif
- struct pci_controller *phb = (struct pci_controller *)token;
PPCDBG(PPCDBG_TCE, "Entering create_pci_bus_tce_table.\n");
- PPCDBG(PPCDBG_TCE, "\tbusNumber = 0x%lx, token = 0x%lx.\n",
- busNumber, token);
- if ( busNumber > 254 ) {
- PPCDBG(PPCDBG_TCE, "PCI Bus TCE table failed.\n");
- PPCDBG(PPCDBG_TCE, " Invalid bus number %u\n", busNumber );
- return;
- }
+ PPCDBG(PPCDBG_TCE, "\ttoken = 0x%lx\n", token);
newTceTable = kmalloc( sizeof(struct TceTable), GFP_KERNEL );
- PPCDBG(PPCDBG_TCE, "\tnewTceTable = 0x%lx\n", newTceTable);
- pciBusTceTableParms.busNumber = busNumber;
- pciBusTceTableParms.virtualBusFlag = 0;
-
-#ifdef CONFIG_PPC_ISERIES
- parmsPtr = virt_to_absolute( (u64)&pciBusTceTableParms );
+ if(_machine == _MACH_iSeries) {
+ if ( token > 254 ) {
+ PPCDBG(PPCDBG_TCE, "PCI Bus TCE table failed.\n");
+ PPCDBG(PPCDBG_TCE, " Invalid bus number %u\n", token );
+ return;
+ }
- /*
- * Call HV with the architected data structure to get TCE table info.
- * Put the returned data into the Linux representation of the TCE
- * table data.
- */
- HvCallXm_getTceTableParms( parmsPtr );
- newTceTable->size = pciBusTceTableParms.size;
- newTceTable->busNumber = pciBusTceTableParms.busNumber;
- newTceTable->startOffset = pciBusTceTableParms.startOffset;
- newTceTable->index = pciBusTceTableParms.index;
-#else
- getTceTableParms( phb, newTceTable );
-#endif
-
- t = build_tce_table( newTceTable );
- if ( t ) {
- tceTables[busNumber] = t;
- PPCDBG(PPCDBG_TCE, "PCI Bus TCE table built successfully.\n");
- PPCDBG(PPCDBG_TCE, " TCE table size = %ld entries\n",
- (unsigned long)t->size*(PAGE_SIZE/sizeof(union Tce)) );
- PPCDBG(PPCDBG_TCE, " TCE table token = %d\n",
- (unsigned)t->index );
- PPCDBG(PPCDBG_TCE, " TCE table start entry = 0x%lx\n",
- (unsigned long)t->startOffset );
+ pciBusTceTableParms.busNumber = token;
+ pciBusTceTableParms.virtualBusFlag = 0;
+ parmsPtr = virt_to_absolute( (u64)&pciBusTceTableParms );
+
+ /*
+ * Call HV with the architected data structure to get TCE table
+ * info. Put the returned data into the Linux representation
+ * of the TCE table data.
+ */
+ HvCallXm_getTceTableParms( parmsPtr );
+
+ newTceTable->size = pciBusTceTableParms.size;
+ newTceTable->busNumber = pciBusTceTableParms.busNumber;
+ newTceTable->startOffset = pciBusTceTableParms.startOffset;
+ newTceTable->index = pciBusTceTableParms.index;
+
+ builtTceTable = build_tce_table( newTceTable );
+ tceTables[token] = builtTceTable;
+ return;
+ } else if(_machine == _MACH_pSeries) {
+ struct pci_controller *phb = (struct pci_controller *)token;
+ struct device_node *phbdn = (struct device_node *)phb->arch_data;
+
+ getTceTableParmsPSeries(phb, newTceTable);
+ builtTceTable = build_tce_table( newTceTable );
+ phbdn->tce_table = builtTceTable;
}
- else {
+
+ if(builtTceTable == NULL ) {
kfree( newTceTable );
PPCDBG(PPCDBG_TCE, "PCI Bus TCE table failed.\n");
return;
}
-#ifndef CONFIG_PPC_ISERIES
+ if (_machine != _MACH_pSeries)
+ return;
+
/* Do not allow DMA's to the 1st 16MB of PCI space in order
* to account for the I/O hole and aliases.
*
@@ -649,12 +754,7 @@
resv_tce_range_top_level(newTceTable, rtas.base,
(rtas.size) >> PAGE_SHIFT);
-#if 1
/* Initialize the table to have a one-to-one mapping over RTAS */
-
- /* DRENG strictly speaking, the RPA says this should be done.
- * I do not see how it can really be a valid thing to require however.
- */
{
unsigned long tce_entry, *tce_entryp, i;
@@ -669,16 +769,10 @@
tce_entry += (1UL << PAGE_SHIFT);
}
}
-#endif
-#endif
}
-static void getTceTableParms( struct pci_controller *phb,
- struct TceTable *newTceTable ) {
-#if 0
- struct pci_dev *dev;
- struct device_node *np;
-#endif
+static void getTceTableParmsPSeries(struct pci_controller *phb,
+ struct TceTable *newTceTable ) {
phandle node;
unsigned long i;
@@ -712,18 +806,9 @@
}
i++;
}
-
-#if 0
- pci_for_each_dev(dev) {
- np = pci_device_to_OF_node(dev);
- node = np->node;
- bus_number = dev->bus->number;
- create_pci_bus_tce_table( unsigned long bus_number );
- node = hose->arch_data->node;
- }
-#endif
}
+
/* Allocates a contiguous real buffer and creates TCEs over it.
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (tce) of the first page.
@@ -733,7 +818,7 @@
{
struct TceTable * tbl;
void *ret = NULL;
- unsigned order, nPages, bus;
+ unsigned order, nPages;
dma_addr_t tce;
int tceType;
@@ -748,24 +833,13 @@
/* If no pci_dev then use virtual bus */
if (hwdev == NULL ) {
- bus = 255;
tceType = TCE_VB;
- }
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = get_tce_table_index( hwdev );
- // bus = ISERIES_GET_BUS( hwdev );
+ } else {
tceType = TCE_PCI;
-#else
- BUG();
- return NULL;
-#endif /* CONFIG_PCI */
}
- tbl = tceTables[bus];
+ tbl = get_tce_table(hwdev);
+
if ( tbl ) {
/* Alloc enough pages (and possibly more) */
ret = (void *)__get_free_pages( GFP_ATOMIC, order );
@@ -785,9 +859,9 @@
*dma_handle = tce;
}
}
- else
- PPCDBG(PPCDBG_TCE, "pci_alloc_consistent: __get_free_pages failed for order = %d\n", order);
+ else PPCDBG(PPCDBG_TCE, "pci_alloc_consistent: __get_free_pages failed for order = %d\n", order);
}
+ else PPCDBG(PPCDBG_TCE, "pci_alloc_consistent: get_tce_table failed for 0x%016lx\n", hwdev);
PPCDBG(PPCDBG_TCE, "\tpci_alloc_consistent: dma_handle = 0x%16.16lx\n", *dma_handle);
PPCDBG(PPCDBG_TCE, "\tpci_alloc_consistent: return = 0x%16.16lx\n", ret);
@@ -798,7 +872,7 @@
void *vaddr, dma_addr_t dma_handle)
{
struct TceTable * tbl;
- unsigned order, nPages, bus;
+ unsigned order, nPages;
PPCDBG(PPCDBG_TCE, "pci_free_consistent:\n");
PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, size = 0x%16.16lx, dma_handle = 0x%16.16lx, vaddr = 0x%16.16lx\n", hwdev, size, dma_handle, vaddr);
@@ -811,31 +885,10 @@
PPCDBG(PPCDBG_TCE, "pci_free_consistent: order=%d, size=%d, nPages=%d, dma_handle=%016lx, vaddr=%016lx\n",
order, size, nPages, (unsigned long)dma_handle, (unsigned long)vaddr );
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL )
- bus = 255;
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = get_tce_table_index( hwdev );
- // bus = ISERIES_GET_BUS( hwdev );
-#else
- BUG();
- return;
-#endif /* CONFIG_PCI */
- }
-
- if ( bus > 255 ) {
- PPCDBG(PPCDBG_TCE, "pci_free_consistent: invalid bus # %d\n", bus );
- PPCDBG(PPCDBG_TCE, "pci_free_consistent: hwdev = %08lx\n", (unsigned long)hwdev );
- }
-
- tbl = tceTables[bus];
+ tbl = get_tce_table(hwdev);
if ( tbl ) {
- free_tces( tbl, dma_handle, order, nPages );
+ ppc_md.tce_free(tbl, dma_handle, order, nPages);
free_pages( (unsigned long)vaddr, order );
}
}
@@ -851,7 +904,7 @@
struct TceTable * tbl;
dma_addr_t dma_handle;
unsigned long uaddr;
- unsigned order, nPages, bus;
+ unsigned order, nPages;
int tceType;
PPCDBG(PPCDBG_TCE, "pci_map_single:\n");
@@ -868,25 +921,12 @@
/* If no pci_dev then use virtual bus */
if (hwdev == NULL ) {
- bus = 255;
tceType = TCE_VB;
- }
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = get_tce_table_index( hwdev );
- // bus = ISERIES_GET_BUS( hwdev );
+ } else {
tceType = TCE_PCI;
-#else
- BUG();
- return NO_TCE;
-#endif /* CONFIG_PCI */
-
}
- tbl = tceTables[bus];
+ tbl = get_tce_table(hwdev);
if ( tbl ) {
dma_handle = get_tces( tbl, order, vaddr, nPages, tceType,
@@ -900,7 +940,7 @@
void pci_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction )
{
struct TceTable * tbl;
- unsigned order, nPages, bus;
+ unsigned order, nPages;
PPCDBG(PPCDBG_TCE, "pci_unmap_single:\n");
PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, size = 0x%16.16lx, direction = 0x%16.16lx, dma_handle = 0x%16.16lx\n", hwdev, size, direction, dma_handle);
@@ -915,31 +955,10 @@
PPCDBG(PPCDBG_TCE, "pci_unmap_single: order=%d, size=%d, nPages=%d, dma_handle=%016lx\n",
order, size, nPages, (unsigned long)dma_handle );
- /* If no pci_dev then use virtual bus */
- if (hwdev == NULL )
- bus = 255;
- else {
-#ifdef CONFIG_PCI
- /* Get the iSeries bus # to use as an index
- * into the TCE table array
- */
- bus = get_tce_table_index( hwdev );
- // bus = ISERIES_GET_BUS( hwdev );
-#else
- BUG();
- return;
-#endif /* CONFIG_PCI */
- }
-
- if ( bus > 255 ) {
- PPCDBG(PPCDBG_TCE, "pci_unmap_single: invalid bus # %d\n", bus );
- PPCDBG(PPCDBG_TCE, "pci_unmap_single: hwdev = %08lx\n", (unsigned long)hwdev );
- }
-
- tbl = tceTables[bus];
+ tbl = get_tce_table(hwdev);
if ( tbl )
- free_tces( tbl, dma_handle, order, nPages );
+ ppc_md.tce_free(tbl, dma_handle, order, nPages);
}
@@ -1113,8 +1132,8 @@
}
for (i=0; i 255 ) {
- PPCDBG(PPCDBG_TCE, "pci_unmap_sg: invalid bus # %d\n", bus );
- PPCDBG(PPCDBG_TCE, "pci_unmap_sg: hwdev = %08lx\n", (unsigned long)hwdev );
- }
-
-
- tbl = tceTables[bus];
+ tbl = get_tce_table(hwdev);
if ( tbl )
- free_tces( tbl, dma_start_page, order, numTces );
+ ppc_md.tce_free( tbl, dma_start_page, order, numTces );
}
-static unsigned long setTce( unsigned long base,
- unsigned long tce_num,
- unsigned long tce_data) {
- union Tce *tce_addr;
-
- PPCDBG(PPCDBG_TCE, "setTce:\n");
- PPCDBG(PPCDBG_TCE, "\tbase = 0x%lx\n", base);
- PPCDBG(PPCDBG_TCE, "\ttce_num = 0x%lx\n", tce_num);
- PPCDBG(PPCDBG_TCE, "\ttce_data = 0x%lx\n", tce_data);
-
- tce_addr = ((union Tce *)base) + tce_num;
-
- PPCDBG(PPCDBG_TCE, "\ttce_addr = 0x%lx\n", tce_addr);
-
- *tce_addr = (union Tce)tce_data;
-
- /* Make sure the update is visible to hardware. */
- __asm__ __volatile__ ("sync" : : : "memory");
-
- return(0);
-}
-
+/*
+ * phb_tce_table_init
+ *
+ * Function: Display TCE config registers. Could be easily changed
+ * to initialize the hardware to use TCEs.
+ */
unsigned long phb_tce_table_init(struct pci_controller *phb) {
unsigned int r, cfg_rw, i;
unsigned long r64;
@@ -1320,7 +1288,8 @@
}
PPCDBG(PPCDBG_TCEINIT, "phb_tce_table_init: done\n");
- // create_pci_bus_tce_table(phb->number, (unsigned long)phb);
+
+ return(0);
}
/*
@@ -1380,4 +1349,18 @@
}
return(0);
+}
+
+
+/* These are called very early. */
+void tce_init_pSeries(void)
+{
+ ppc_md.tce_build = tce_build_pSeries;
+ ppc_md.tce_free = tce_free_pSeries;
+}
+
+void tce_init_iSeries(void)
+{
+ ppc_md.tce_build = tce_build_iSeries;
+ ppc_md.tce_free = tce_free_iSeries;
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pci_dn.c linuxppc64_2_4/arch/ppc64/kernel/pci_dn.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/pci_dn.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/arch/ppc64/kernel/pci_dn.c Tue Sep 11 07:12:11 2001
@@ -0,0 +1,326 @@
+/*
+ * pci_dn.c
+ *
+ * Copyright (C) 2001 Todd Inglett, IBM Corporation
+ *
+ * PCI manipulation via device_nodes.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "pci.h"
+
+/* Traverse_func that inits the PCI fields of the device node.
+ * NOTE: this *must* be done before read/write config to the device.
+ */
+static void * __init
+update_dn_pci_info(struct device_node *dn, void *data)
+{
+ struct pci_controller *phb = (struct pci_controller *)data;
+ u32 *regs;
+ char *device_type = get_property(dn, "device_type", 0);
+
+ dn->phb = phb;
+ if (device_type && strcmp(device_type, "pci") == 0 && get_property(dn, "class-code", 0) == 0) {
+ /* special case for PHB's. Sigh. */
+ regs = (u32 *)get_property(dn, "bus-range", 0);
+ dn->busno = regs[0];
+ dn->devfn = 0; /* assumption */
+ } else {
+ regs = (u32 *)get_property(dn, "reg", 0);
+ if (regs) {
+ /* First register entry is addr (00BBSS00) */
+ dn->busno = (regs[0] >> 16) & 0xff;
+ dn->devfn = (regs[0] >> 8) & 0xff;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Hit all the BARs of all the devices with values from OF.
+ * This is unnecessary on most systems, but also harmless.
+ */
+static void * __init
+write_OF_bars(struct device_node *dn, void *data)
+{
+ int i;
+ u32 oldbar, newbar, newbartest;
+ u8 config_offset;
+ char *name = get_property(dn, "name", 0);
+ char *device_type = get_property(dn, "device_type", 0);
+ char devname[128];
+ sprintf(devname, "%04x:%02x.%x %s (%s)", dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn), name ? name : "", device_type ? device_type : "");
+
+ if (device_type && strcmp(device_type, "pci") == 0 &&
+ get_property(dn, "class-code", 0) == 0)
+ return NULL; /* This is probably a phb. Skip it. */
+
+ if (dn->n_addrs == 0)
+ return NULL; /* This is normal for some adapters or bridges */
+
+ if (dn->addrs == NULL) {
+ /* This shouldn't happen. */
+ printk(KERN_WARNING "write_OF_bars %s: device has %d BARs, but no addrs recorded\n", devname, dn->n_addrs);
+ return NULL;
+ }
+
+#ifndef CONFIG_PPC_ISERIES
+ for (i = 0; i < dn->n_addrs; i++) {
+ newbar = dn->addrs[i].address;
+ config_offset = dn->addrs[i].space & 0xff;
+ if (ppc_md.pcibios_read_config_dword(dn, config_offset, &oldbar) != PCIBIOS_SUCCESSFUL) {
+ printk(KERN_WARNING "write_OF_bars %s: read BAR%d failed\n", devname, i);
+ continue;
+ }
+ /* Need to update this BAR. */
+ if (ppc_md.pcibios_write_config_dword(dn, config_offset, newbar) != PCIBIOS_SUCCESSFUL) {
+ printk(KERN_WARNING "write_OF_bars %s: write BAR%d with 0x%08x failed (old was 0x%08x)\n", devname, i, newbar, oldbar);
+ continue;
+ }
+ /* sanity check */
+ if (ppc_md.pcibios_read_config_dword(dn, config_offset, &newbartest) != PCIBIOS_SUCCESSFUL) {
+ printk(KERN_WARNING "write_OF_bars %s: sanity test read BAR%d failed?\n", devname, i);
+ continue;
+ }
+ if ((newbar & PCI_BASE_ADDRESS_MEM_MASK) != (newbartest & PCI_BASE_ADDRESS_MEM_MASK)) {
+ printk(KERN_WARNING "write_OF_bars %s: oops...BAR%d read back as 0x%08x%s!\n", devname, i, newbartest, (oldbar & PCI_BASE_ADDRESS_MEM_MASK) == (newbartest & PCI_BASE_ADDRESS_MEM_MASK) ? " (original value)" : "");
+ continue;
+ }
+ }
+#endif
+ return NULL;
+}
+
+#if 0
+/* Traverse_func that starts the BIST (self test) */
+static void * __init
+startBIST(struct device_node *dn, void *data)
+{
+ struct pci_controller *phb = (struct pci_controller *)data;
+ u8 bist;
+
+ char *name = get_property(dn, "name", 0);
+ udbg_printf("startBIST: %s phb=%p, device=%p\n", name ? name : "", phb, dn);
+
+ if (ppc_md.pcibios_read_config_byte(dn, PCI_BIST, &bist) == PCIBIOS_SUCCESSFUL) {
+ if (bist & PCI_BIST_CAPABLE) {
+ udbg_printf(" -> is BIST capable!\n", phb, dn);
+ /* Start bist here */
+ }
+ }
+ return NULL;
+}
+#endif
+
+
+/******************************************************************
+ * Traverse a device tree stopping each PCI device in the tree.
+ * This is done depth first. As each node is processed, a "pre"
+ * function is called, the children are processed recursively, and
+ * then a "post" function is called.
+ *
+ * The "pre" and "post" funcs return a value. If non-zero
+ * is returned from the "pre" func, the traversal stops and this
+ * value is returned. The return value from "post" is not used.
+ * This return value is useful when using traverse as
+ * a method of finding a device.
+ *
+ * NOTE: we do not run the funcs for devices that do not appear to
+ * be PCI except for the start node which we assume (this is good
+ * because the start node is often a phb which may be missing PCI
+ * properties).
+ * We use the class-code as an indicator. If we run into
+ * one of these nodes we also assume its siblings are non-pci for
+ * performance.
+ *
+ ******************************************************************/
+void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data)
+{
+ struct device_node *dn, *nextdn;
+ void *ret;
+
+ if (pre && (ret = pre(start, data)) != NULL)
+ return ret;
+ for (dn = start->child; dn; dn = nextdn) {
+ nextdn = NULL;
+ if (get_property(dn, "class-code", 0)) {
+ if (pre && (ret = pre(dn, data)) != NULL)
+ return ret;
+ if (dn->child) {
+ /* Depth first...do children */
+ nextdn = dn->child;
+ } else if (dn->sibling) {
+ /* ok, try next sibling instead. */
+ nextdn = dn->sibling;
+ } else {
+ /* no more children or siblings...call "post" */
+ if (post)
+ post(dn, data);
+ }
+ }
+ if (!nextdn) {
+ /* Walk up to next valid sibling. */
+ do {
+ dn = dn->parent;
+ if (dn == start)
+ return NULL;
+ } while (dn->sibling == NULL);
+ nextdn = dn->sibling;
+ }
+ }
+ return NULL;
+}
+
+/* Same as traverse_pci_devices except this does it for all phbs.
+ */
+void *traverse_all_pci_devices(traverse_func pre)
+{
+ struct pci_controller* phb;
+ void *ret;
+ for (phb=hose_head;phb;phb=phb->next)
+ if ((ret = traverse_pci_devices((struct device_node *)phb->arch_data, pre, NULL, phb)) != NULL)
+ return ret;
+ return NULL;
+}
+
+
+/* Traversal func that looks for a value.
+ * If found, the device_node is returned (thus terminating the traversal).
+ */
+static void *
+is_devfn_node(struct device_node *dn, void *data)
+{
+ int busno = ((unsigned long)data >> 8) & 0xff;
+ int devfn = ((unsigned long)data) & 0xff;
+ return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL;
+}
+
+
+/* This is the "slow" path for looking up a device_node from a
+ * pci_dev. It will hunt for the device under it's parent's
+ * phb and then update sysdata for a future fastpath.
+ *
+ * It may also do fixups on the actual device since this happens
+ * on the first read/write.
+ *
+ * Note that it also must deal with devices that don't exist.
+ * In this case it may probe for real hardware ("just in case")
+ * and add a device_node to the device tree if necessary.
+ *
+ */
+struct device_node *fetch_dev_dn(struct pci_dev *dev)
+{
+ struct device_node *orig_dn = (struct device_node *)dev->sysdata;
+ struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */
+ struct device_node *phb_dn;
+ struct device_node *dn;
+ unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
+
+ phb_dn = (struct device_node *)(phb->arch_data);
+ dn = (struct device_node *)traverse_pci_devices(phb_dn, is_devfn_node, NULL, (void *)searchval);
+ if (dn) {
+ dev->sysdata = dn;
+ /* ToDo: call some device init hook here */
+ } else {
+ /* ToDo: device not found...probe for it anyway with a fake dn?
+ struct device_node fake_dn;
+ memset(&fake_dn, 0, sizeof(fake_dn));
+ fake_dn.phb = phb;
+ fake_dn.busno = dev->bus->number;
+ fake_dn.devfn = dev->devfn;
+ ... now do ppc_md.pcibios_read_config_dword(&fake_dn.....)
+ ... if ok, alloc a real device_node and dn = real_dn;
+ */
+ }
+ return dn;
+}
+
+
+/******************************************************************
+ * Actually initialize the phbs.
+ * The buswalk on this phb has not happened yet.
+ ******************************************************************/
+void __init
+pci_devs_phb_init(void)
+{
+ /* This must be done first so the device nodes have valid pci info! */
+ traverse_all_pci_devices(update_dn_pci_info);
+
+ /* Hack for regatta which does not init the bars correctly */
+ traverse_all_pci_devices(write_OF_bars);
+#if 0
+ traverse_all_pci_devices(startBIST);
+ mdelay(5000);
+ traverse_all_pci_devices(checkBIST);
+#endif
+}
+
+
+static void __init
+pci_fixup_bus_sysdata_list(struct list_head *bus_list)
+{
+ struct list_head *ln;
+ struct pci_bus *bus;
+ int newnum;
+
+ for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+ bus = pci_bus_b(ln);
+ if (bus->self) {
+ bus->sysdata = bus->self->sysdata;
+ /* Also fixup the bus number to include the PHB# in the next byte */
+ newnum = (PCI_GET_DN(bus)->phb->global_number << 8) | bus->number;
+ bus->number = newnum;
+ sprintf(bus->name, "PCI Bus #%x", bus->number);
+ }
+ pci_fixup_bus_sysdata_list(&bus->children);
+ }
+}
+
+
+/******************************************************************
+ * Fixup the bus->sysdata ptrs to point to the bus' device_node.
+ * This is done late in pcibios_init(). We do this mostly for
+ * sanity, but pci_dma.c uses these at DMA time so they must be
+ * correct.
+ * To do this we recurse down the bus hierarchy. Note that PHB's
+ * have bus->self == NULL, but fortunately bus->sysdata is already
+ * correct in this case.
+ ******************************************************************/
+void __init
+pci_fix_bus_sysdata(void)
+{
+ pci_fixup_bus_sysdata_list(&pci_root_buses);
+}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/pmac_nvram.c linuxppc64_2_4/arch/ppc64/kernel/pmac_nvram.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/pmac_nvram.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/pmac_nvram.c Wed Sep 5 13:56:40 2001
@@ -260,7 +260,7 @@
#endif
for (i=0; iaddrs[0].address, dp->addrs[0].size);
nvram_mult = 1;
} else if (nvram_naddrs == 1) {
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/ppc-stub.c linuxppc64_2_4/arch/ppc64/kernel/ppc-stub.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/ppc-stub.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/ppc-stub.c Fri Sep 14 22:14:50 2001
@@ -737,11 +737,3 @@
return 1;
}
-
-/* I don't know why other platforms don't need this. The function for
- * the 8xx is found in arch/ppc/8xx_io/uart.c. -- Dan
- */
-void
-kgdb_map_scc(void)
-{
-}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/ppc_asm.h linuxppc64_2_4/arch/ppc64/kernel/ppc_asm.h
--- linux-2.4.9-ac10/arch/ppc64/kernel/ppc_asm.h Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/ppc_asm.h Fri Sep 14 10:05:47 2001
@@ -48,30 +48,6 @@
sync; \
isync
-/* iSeries LPAR uses an event queue to signal I/O events
- This code checks the queue */
-
-#define CHECKLPQUEUE(ra,rb,rc) \
- mfspr ra,SPRG3; /* Get PACA address */\
- ld ra,PACALPQUEUE(ra); /* Get LpQueue address */\
- cmpi 0,ra,0; /* Does LpQueue exist? */\
- beq 99f; /* No? - then skip rest */\
- ld rb,LPQCUREVENTPTR(ra); /* Get current LpEvent */\
- lbz rb,LPEVENTFLAGS(rb); /* Get valid bit */\
- lbz rc,LPQOVERFLOW(ra); /* Get LpQueue overflow */\
- andi. ra,rb,0x0080; /* Isolate valid bit */\
- or. ra,ra,rc; /* 0 == no pending events */\
-99:
-
-#define CHECKDECR(ra,rb) \
- mfspr rb,SPRG3; /* Get Paca address */\
- lbz ra,PACALPPACA+LPPACADECRINT(rb); /* Get DECR int flag */\
- cmpi 0,ra,0; /* DECR occurred in hypervisor ? */\
- beq 99f; /* If not, skip rest */\
- xor ra,ra,ra; \
- stb ra,PACALPPACA+LPPACADECRINT(rb); /* Clear DECR int flag */\
-99:
-
#define CHECKANYINT(ra,rb) \
mfspr rb,SPRG3; /* Get Paca address */\
ld ra,PACALPPACA+LPPACAANYINT(rb); /* Get pending interrupt flags */\
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/ppc_ksyms.c linuxppc64_2_4/arch/ppc64/kernel/ppc_ksyms.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/ppc_ksyms.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/ppc_ksyms.c Fri Sep 14 20:12:59 2001
@@ -50,7 +50,6 @@
/* Tell string.h we don't want memcpy etc. as cpp defines */
#define EXPORT_SYMTAB_STROPS
-extern void transfer_to_handler(void);
extern void syscall_trace(void);
extern void do_IRQ(struct pt_regs *regs, int isfake);
extern void SystemResetException(struct pt_regs *regs);
@@ -67,10 +66,8 @@
int abs(int);
extern unsigned long ret_to_user_hook;
-EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_signal);
EXPORT_SYMBOL(syscall_trace);
-EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
EXPORT_SYMBOL(SystemResetException);
EXPORT_SYMBOL(MachineCheckException);
@@ -87,6 +84,7 @@
#endif /* CONFIG_SMP */
EXPORT_SYMBOL(isa_io_base);
+EXPORT_SYMBOL(isa_io_limit);
EXPORT_SYMBOL(isa_mem_base);
EXPORT_SYMBOL(pci_dram_offset);
@@ -178,6 +176,9 @@
EXPORT_SYMBOL(__global_sti);
EXPORT_SYMBOL(__global_save_flags);
EXPORT_SYMBOL(__global_restore_flags);
+#endif
+#ifdef CONFIG_PPC_ISERIES
+EXPORT_SYMBOL(int_control);
#endif
#ifndef CONFIG_MACH_SPECIFIC
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/process.c linuxppc64_2_4/arch/ppc64/kernel/process.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/process.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/process.c Fri Sep 7 07:57:15 2001
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
@@ -509,82 +510,29 @@
return error;
}
-
-unsigned long find_hpte(unsigned long);
-
-static __inline__ void set_pp_bit(unsigned long pp, HPTE *addr)
-{
- unsigned long old;
- unsigned long *p = (unsigned long *)(&(addr->dw1));
-
- __asm__ __volatile__(
-"1: ldarx %0,0,%3\n\
- rldimi %0,%2,0,62\n\
- stdcx. %0,0,%3\n\
- bne 1b"
- : "=&r" (old), "=m" (*p)
- : "r" (pp), "r" (p), "m" (*p)
- : "cc");
-}
-
-
-static void updateStackHptePP( unsigned long newpp, unsigned long ea )
-{
- unsigned long vsid,va,vpn;
- long slot;
-
-
- vsid = get_kernel_vsid( ea );
- va = ( vsid << 28 ) | ( ea & 0x0fffffff );
- vpn = va >> PAGE_SHIFT;
-
- slot = find_hpte( vpn );
-
-
- if ( _machine == _MACH_iSeries ) {
- HvCallHpt_setPp( slot, newpp );
- }
- else {
-
- HPTE * hptep = htab_data.htab + slot;
-
- set_pp_bit(newpp , hptep );
-
- /* Ensure it is out of the tlb too */
- _tlbie( va );
-
-
- /* Ensure it is visible before validating */
- __asm__ __volatile__ ("eieio" : : : "memory");
-
-
- __asm__ __volatile__ ("ptesync" : : : "memory");
-
-
- }
-}
-
-
struct task_struct * alloc_task_struct(void) {
- struct task_struct * new_task_ptr;
+ struct task_struct * new_task_ptr;
- new_task_ptr = ((struct task_struct *) __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)));
+ new_task_ptr = ((struct task_struct *)
+ __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)));
- /* Set the second page to be write protected - prevent kernel stack overflow */
- updateStackHptePP( PP_RXRX , (unsigned long)new_task_ptr + PAGE_SIZE );
+ /* Set the second page to be write protected - prevent kernel
+ * stack overflow
+ */
+ updateBoltedHptePP(PP_RXRX ,(unsigned long)new_task_ptr + PAGE_SIZE);
- return new_task_ptr;
+ return new_task_ptr;
}
void free_task_struct(struct task_struct * task_ptr) {
- if (atomic_read(&(virt_to_page(task_ptr)->count)) == 1) {
- updateStackHptePP( PP_RWXX , (unsigned long)task_ptr + PAGE_SIZE );
- }
- free_pages((unsigned long)(task_ptr), get_order(THREAD_SIZE));
+ if (atomic_read(&(virt_to_page(task_ptr)->count)) == 1) {
+ updateBoltedHptePP(PP_RWXX,
+ (unsigned long)task_ptr + PAGE_SIZE );
+ }
+ free_pages((unsigned long)(task_ptr), get_order(THREAD_SIZE));
}
-
void
print_backtrace(unsigned long *sp)
{
@@ -604,88 +552,6 @@
}
printk("\n");
}
-
-#if 0
-/*
- * Low level print for debugging - Cort
- */
-int __init ll_printk(const char *fmt, ...)
-{
- va_list args;
- char buf[256];
- int i;
-
- va_start(args, fmt);
- i=vsprintf(buf,fmt,args);
- ll_puts(buf);
- va_end(args);
- return i;
-}
-
-int lines = 24, cols = 80;
-int orig_x = 0, orig_y = 0;
-
-void puthex(unsigned long val)
-{
- unsigned char buf[10];
- int i;
- for (i = 7; i >= 0; i--)
- {
- buf[i] = "0123456789ABCDEF"[val & 0x0F];
- val >>= 4;
- }
- buf[8] = '\0';
- prom_print(buf);
-}
-
-void __init ll_puts(const char *s)
-{
- int x,y;
- char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000;
- char c;
- extern int mem_init_done;
-
- if ( mem_init_done ) /* assume this means we can printk */
- {
- printk(s);
- return;
- }
-
- /*
- * can't ll_puts on chrp without openfirmware yet.
- * vidmem just needs to be setup for it.
- * -- Cort
- */
- if ( _machine != _MACH_prep )
- return;
- x = orig_x;
- y = orig_y;
-
- while ( ( c = *s++ ) != '\0' ) {
- if ( c == '\n' ) {
- x = 0;
- if ( ++y >= lines ) {
- /*scroll();*/
- /*y--;*/
- y = 0;
- }
- } else {
- vidmem [ ( x + cols * y ) * 2 ] = c;
- if ( ++x >= cols ) {
- x = 0;
- if ( ++y >= lines ) {
- /*scroll();*/
- /*y--;*/
- y = 0;
- }
- }
- }
- }
-
- orig_x = x;
- orig_y = y;
-}
-#endif
/*
* These bracket the sleeping functions..
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/prom.c linuxppc64_2_4/arch/ppc64/kernel/prom.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/prom.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/prom.c Sun Sep 16 20:15:17 2001
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#ifdef DEBUG_YABOOT
#define call_yaboot(FUNC,...) \
@@ -66,6 +67,7 @@
#include
#include
#include "open_pic.h"
+#include
#include
#ifdef CONFIG_FB
@@ -152,13 +154,13 @@
0, /* disp_node */
{0,0,0,{0},NULL}, /* args */
0, /* version */
- 32 /* encode_phys_size */
+ 32, /* encode_phys_size */
+ 0 /* bi_rec pointer */
#ifdef DEBUG_YABOOT
,NULL /* yaboot */
#endif
};
-int cpu_hw_index[NR_CPUS] = {0};
char *prom_display_paths[FB_MAX] __initdata = { 0, };
unsigned int prom_num_displays = 0;
@@ -194,6 +196,7 @@
static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
static unsigned long check_display(unsigned long);
static int prom_next_node(phandle *);
+static void prom_bi_rec_init(unsigned long);
#ifdef CONFIG_MSCHUNKS
static unsigned long prom_initialize_mschunks(unsigned long);
@@ -330,6 +333,8 @@
prom_print(RELOC("prom_initialize_naca: start...\n"));
#endif
+ _naca->pftSize = 0; /* ilog2 of htab size. computed below. */
+
for (node = 0; prom_next_node(&node); ) {
type[0] = 0;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
@@ -429,6 +434,25 @@
_naca->physicalMemorySize = lmb_phys_mem_size();
+ if (RELOC(_machine) == _MACH_pSeries) {
+ unsigned long rnd_mem_size, pteg_count;
+
+ /* round mem_size up to next power of 2 */
+ rnd_mem_size = 1UL << __ilog2(_naca->physicalMemorySize);
+ if (rnd_mem_size < _naca->physicalMemorySize)
+ rnd_mem_size <<= 1;
+
+ /* # pages / 2 */
+ pteg_count = (rnd_mem_size >> (12 + 1));
+
+ _naca->pftSize = __ilog2(pteg_count << 7);
+ }
+
+ if (_naca->pftSize == 0) {
+ prom_print(RELOC("prom: failed to compute pftSize!\n"));
+ PROM_BUG();
+ }
+
/*
* Hardcode to GP size. I am not sure where to get this info
* in general, as there does not appear to be a slb-size OF
@@ -445,6 +469,10 @@
prom_print_hex(_naca->physicalMemorySize);
prom_print_nl();
+ prom_print(RELOC("naca->pftSize = 0x"));
+ prom_print_hex(_naca->pftSize);
+ prom_print_nl();
+
prom_print(RELOC("naca->dCacheL1LineSize = 0x"));
prom_print_hex(_naca->dCacheL1LineSize);
prom_print_nl();
@@ -477,6 +505,10 @@
prom_print_hex(_naca->interrupt_controller);
prom_print_nl();
+ prom_print(RELOC("_machine = 0x"));
+ prom_print_hex(RELOC(_machine));
+ prom_print_nl();
+
prom_print(RELOC("prom_initialize_naca: end...\n"));
#endif
@@ -496,16 +528,18 @@
unsigned long mem_size, lmb_base, lmb_size;
unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
+#ifdef CONFIG_MSCHUNKS
#if 1
- /* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
- unsigned long io_base = 3UL<<30;
- unsigned long io_size = 1UL<<30;
+ /* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
+ unsigned long io_base = 3UL<<30;
+ unsigned long io_size = 1UL<<30;
unsigned long have_630 = 1; /* assume we have a 630 */
#else
unsigned long io_base = ;
unsigned long io_size = ;
#endif
+#endif
lmb_init();
@@ -529,6 +563,7 @@
lmb_size = reg.addr64[i].size;
}
+#ifdef CONFIG_MSCHUNKS
if ( lmb_addrs_overlap(lmb_base,lmb_size,
io_base,io_size) ) {
/* If we really have dram here, then we don't
@@ -536,6 +571,7 @@
*/
have_630 = 0;
}
+#endif
if ( lmb_add(lmb_base, lmb_size) < 0 )
prom_print(RELOC("Too many LMB's, discarding this one...\n"));
else
@@ -544,8 +580,10 @@
}
+#ifdef CONFIG_MSCHUNKS
if ( have_630 && lmb_addrs_overlap(0,mem_size,io_base,io_size) )
lmb_add_io(io_base, io_size);
+#endif
lmb_analyze();
@@ -628,22 +666,22 @@
}
#ifdef DEBUG_PROM
- prom_print(RELOC("rtas->base = 0x"));
+ prom_print(RELOC("rtas->base = 0x"));
prom_print_hex(_rtas->base);
prom_print_nl();
- prom_print(RELOC("rtas->entry = 0x"));
+ prom_print(RELOC("rtas->entry = 0x"));
prom_print_hex(_rtas->entry);
prom_print_nl();
- prom_print(RELOC("rtas->size = 0x"));
+ prom_print(RELOC("rtas->size = 0x"));
prom_print_hex(_rtas->size);
prom_print_nl();
- prom_print(RELOC("rtas->event_scan.rate = 0x"));
+ prom_print(RELOC("rtas->event_scan.rate = 0x"));
prom_print_hex(_rtas->event_scan.rate);
prom_print_nl();
- prom_print(RELOC("rtas->event_scan.log = 0x"));
+ prom_print(RELOC("rtas->event_scan.log = 0x"));
prom_print_hex((unsigned long)_rtas->event_scan.log);
prom_print_nl();
- prom_print(RELOC("rtas->event_scan.log_size = 0x"));
+ prom_print(RELOC("rtas->event_scan.log_size = 0x"));
prom_print_hex(_rtas->event_scan.log_size);
prom_print_nl();
#endif
@@ -896,6 +934,7 @@
unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge);
unsigned long secondary_hold = __v2a(*PTRRELOC((unsigned long *)__secondary_hold));
struct Naca *_naca = RELOC(naca);
+ struct Paca *_xPaca = PTRRELOC(&xPaca);
struct prom_t *_prom = PTRRELOC(&prom);
/* Initially, we must have one active CPU. */
@@ -983,7 +1022,7 @@
prom_print_hex(reg);
prom_print_nl();
#endif
- RELOC(cpu_hw_index)[cpuid] = reg;
+ _xPaca[cpuid].xHwProcNum = reg;
prom_print(RELOC("starting cpu "));
prom_print(path);
@@ -1063,10 +1102,15 @@
unsigned long phys;
u32 getprop_rval;
struct Naca *_naca = RELOC(naca);
+ struct Paca *_xPaca = PTRRELOC(&xPaca);
struct prom_t *_prom = PTRRELOC(&prom);
+ /* Default machine type. */
+ RELOC(_machine) = _MACH_pSeries;
+
/* Get a handle to the prom entry point before anything else */
_prom->entry = pp;
+ _prom->bi_recs = (struct bi_record *)r6;
#ifdef DEBUG_YABOOT
call_yaboot(yaboot->dummy,offset>>32,offset&0xffffffff);
@@ -1181,7 +1225,7 @@
cpu_pkg, RELOC("reg"),
&getprop_rval, sizeof(getprop_rval));
_prom->cpu = (int)(unsigned long)getprop_rval;
- cpu_hw_index[0] = _prom->cpu;
+ _xPaca[0].xHwProcNum = _prom->cpu;
#ifdef DEBUG_PROM
prom_print(RELOC("Booting CPU hw index = 0x"));
@@ -1206,6 +1250,8 @@
mem = prom_initialize_lmb(mem);
+ prom_bi_rec_init(mem);
+
mem = prom_instantiate_rtas(mem);
/* Initialize some system info into the Naca early... */
@@ -1229,7 +1275,8 @@
lmb_reserve(0, __pa(RELOC(klimit)));
- prom_initialize_tce_table();
+ if(RELOC(_machine) == _MACH_pSeries)
+ prom_initialize_tce_table();
if ((long) call_prom(RELOC("getprop"), 4, 1,
_prom->chosen,
@@ -1635,8 +1682,8 @@
/* XXX on chrp, offset interrupt numbers for the
8259 by 0, those for the openpic by 16 */
// DRENG Condor -- this info is not actually known yet ...
- cvt_irq = _machine == _MACH_chrp
- && get_property(node, "interrupt-parent", NULL) == 0;
+ cvt_irq = (_machine == _MACH_pSeries)
+ && (get_property(node, "interrupt-parent", NULL) == 0);
np->intrs = (struct interrupt_info *) mem_start;
np->n_intrs = ipsize / isize;
mem_start += np->n_intrs * sizeof(struct interrupt_info);
@@ -1662,7 +1709,7 @@
else
map = NULL;
if (map && l) {
- int i, found, temp_isize;
+ int i, found, temp_isize, temp_asize;
map_size = l>>2;
map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);
asizep = (unsigned int *)get_property(node, "#address-cells", &l);
@@ -1691,22 +1738,29 @@
map+=1; map_size-=1;
parent_node = find_phandle(parent);
temp_isize = isize;
+ temp_asize = 0;
if (parent_node) {
isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);
if (isizep)
temp_isize = *isizep;
+ asizep = (unsigned int *)get_property(parent_node, "#address-cells", &l);
+ if (asizep && l == sizeof(unsigned int))
+ temp_asize = *asizep;
}
if (!found) {
- map += temp_isize;
- map_size-=temp_isize;
+ map += temp_isize + temp_asize;
+ map_size -= temp_isize + temp_asize;
}
}
if (found) {
+ /* Mapped to a new parent. Use the reg and interrupts specified in
+ * the map as the new search parameters. Then search from the parent.
+ */
node = parent_node;
- reg = NULL;
- regpsize = 0;
- interrupts = (unsigned int *)map;
- ipsize = temp_isize*1;
+ reg = map;
+ regpsize = temp_asize;
+ interrupts = map + temp_asize;
+ ipsize = temp_isize;
continue;
}
}
@@ -1933,26 +1987,10 @@
ip = (int *) get_property(np, "AAPL,interrupts", &l);
if (ip != 0) {
np->intrs = (struct interrupt_info *) mem_start;
- if (_machine == _MACH_Pmac) {
- /* for the iMac */
- np->n_intrs = l / sizeof(int);
- /* Hack for BootX on Core99 */
- if (keylargo)
- np->n_intrs = np->n_intrs/2;
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = *ip++;
- if (keylargo)
- np->intrs[i].sense = *ip++;
- else
- np->intrs[i].sense = 1;
- }
- } else {
- /* CHRP machines */
- np->n_intrs = l / (2 * sizeof(int));
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = openpic_to_irq(*ip++);
- np->intrs[i].sense = *ip++;
- }
+ np->n_intrs = l / (2 * sizeof(int));
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = openpic_to_irq(*ip++);
+ np->intrs[i].sense = *ip++;
}
mem_start += np->n_intrs * sizeof(struct interrupt_info);
}
@@ -2345,6 +2383,35 @@
#endif
for (;;)
prom_exit();
+}
+
+
+static void
+prom_bi_rec_init(unsigned long mem)
+{
+ unsigned long offset = reloc_offset();
+ struct prom_t *_prom = PTRRELOC(&prom);
+ struct bi_record *rec;
+
+ if ( _prom->bi_recs == NULL)
+ return;
+
+ for (rec=_prom->bi_recs; rec->tag != BI_LAST ;rec=bi_rec_next(rec) )
+ {
+ switch (rec->tag)
+ {
+#ifdef CONFIG_BLK_DEV_INITRD
+ case BI_INITRD:
+ lmb_reserve(rec->data[0], rec->data[1]);
+ break;
+#endif /* CONFIG_BLK_DEV_INITRD */
+ }
+ }
+ /* The next use of this field will be after relocation
+ * is enabled, so convert this physical address into a
+ * virtual address.
+ */
+ _prom->bi_recs = __va(_prom->bi_recs);
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/ptrace.c linuxppc64_2_4/arch/ppc64/kernel/ptrace.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/ptrace.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/ptrace.c Thu Sep 13 11:54:36 2001
@@ -57,7 +57,7 @@
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
- if (regno <= PT_MQ) {
+ if (regno < PT_SOFTE) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/ptrace32.c linuxppc64_2_4/arch/ppc64/kernel/ptrace32.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/ptrace32.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/ptrace32.c Thu Sep 13 11:54:36 2001
@@ -57,7 +57,7 @@
*/
static inline int put_reg(struct task_struct *task, int regno, unsigned long data)
{
- if (regno <= PT_MQ)
+ if (regno < PT_SOFTE)
{
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE) | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
@@ -319,7 +319,7 @@
if ((addr & 3) || numReg > PT_FPSCR)
break;
/* Insure it is a register we let them change */
- if ((numReg == PT_ORIG_R3) || ((numReg > PT_MQ) && (numReg < PT_FPR0)))
+ if ((numReg == PT_ORIG_R3) || ((numReg > PT_CCR) && (numReg < PT_FPR0)))
break;
if (numReg >= PT_FPR0)
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/rtas-proc.c linuxppc64_2_4/arch/ppc64/kernel/rtas-proc.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/rtas-proc.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/rtas-proc.c Wed Sep 5 13:56:40 2001
@@ -200,7 +200,7 @@
struct proc_dir_entry *entry;
rtas_node = find_devices("rtas");
- if ((rtas_node == 0) || (_machine != _MACH_chrp)) {
+ if ((rtas_node == 0) || (_machine == _MACH_iSeries)) {
return;
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/setup.c linuxppc64_2_4/arch/ppc64/kernel/setup.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/setup.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/setup.c Fri Sep 14 20:12:59 2001
@@ -1,6 +1,6 @@
/*
*
- * Common prep/pmac/chrp boot and setup code.
+ * Common boot and setup code.
*
* Copyright (C) 2001 PPC64 Team, IBM Corp
*
@@ -49,6 +49,7 @@
extern void chrp_init_map_io_space( void );
extern void iSeries_init( void );
extern void iSeries_init_early( void );
+extern void pSeries_init_early( void );
extern void mm_init_ppc64( void );
unsigned long decr_overclock = 1;
@@ -62,6 +63,7 @@
char saved_command_line[256];
unsigned char aux_device_present;
+#ifdef CONFIG_PPC_ISERIES
struct int_control_struct int_control =
{
__no_use_cli,
@@ -69,14 +71,14 @@
__no_use_restore_flags,
__no_use_save_flags
};
+#endif
struct ide_machdep_calls ppc_ide_md;
-int parse_bootinfo(void);
void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7);
unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
-int _machine = _MACH_chrp; /* DRENG prom.c needs this assumption, a better way needs to be found. */
+int _machine = _MACH_unknown;
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
@@ -120,7 +122,7 @@
unsigned long offset = reloc_offset();
struct Naca *_naca = RELOC(naca);
- _naca->debug_switch = PPC_DEBUG_DEFAULT;
+ _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
}
void naca_init(void) {
@@ -152,110 +154,103 @@
}
/*
- * Determine the type of system this we are running on.
- * For the PPC64 kernel, we assume chrp.
- */
-void identify_machine(void) {
- if ( itLpNaca.xLparInstalled == 1 )
- _machine = _MACH_iSeries;
- else
- _machine = _MACH_chrp;
-}
-
-/*
* Do some initial setup of the system. The paramters are those which
* were passed in from the bootloader.
*/
void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7) {
- identify_machine();
-
- switch (_machine) {
- case _MACH_chrp:
- parse_bootinfo();
- chrp_init_map_io_space();
- break;
- case _MACH_iSeries:
+ /* pSeries systems are identified in prom.c via OF. */
+ if ( itLpNaca.xLparInstalled == 1 )
+ _machine = _MACH_iSeries;
+ switch (_machine) {
+ case _MACH_iSeries:
iSeries_init_early();
- break;
- default:
- }
-
- udbg_init();
-
- udbg_puts("\n-----------------------------------------------------\n");
- udbg_puts("Naca Info...\n\n");
- udbg_puts("naca = 0x");
- udbg_puthex((unsigned long)naca);
- udbg_putc('\n');
-
- udbg_puts("naca->processorCount = 0x");
- udbg_puthex(naca->processorCount);
- udbg_putc('\n');
-
- udbg_puts("naca->physicalMemorySize = 0x");
- udbg_puthex(naca->physicalMemorySize);
- udbg_putc('\n');
-
- udbg_puts("naca->dCacheL1LineSize = 0x");
- udbg_puthex(naca->dCacheL1LineSize);
- udbg_putc('\n');
-
- udbg_puts("naca->dCacheL1LogLineSize = 0x");
- udbg_puthex(naca->dCacheL1LogLineSize);
- udbg_putc('\n');
-
- udbg_puts("naca->dCacheL1LinesPerPage = 0x");
- udbg_puthex(naca->dCacheL1LinesPerPage);
- udbg_putc('\n');
-
- udbg_puts("naca->iCacheL1LineSize = 0x");
- udbg_puthex(naca->iCacheL1LineSize);
- udbg_putc('\n');
-
- udbg_puts("naca->iCacheL1LogLineSize = 0x");
- udbg_puthex(naca->iCacheL1LogLineSize);
- udbg_putc('\n');
-
- udbg_puts("naca->iCacheL1LinesPerPage = 0x");
- udbg_puthex(naca->iCacheL1LinesPerPage);
- udbg_putc('\n');
-
- udbg_puts("naca->serialPortAddr = 0x");
- udbg_puthex(naca->serialPortAddr);
- udbg_putc('\n');
-
- udbg_puts("naca->interrupt_controller = 0x");
- udbg_puthex(naca->interrupt_controller);
- udbg_putc('\n');
-
- udbg_printf("\nHTAB Info ...\n\n");
- udbg_printf("htab_data.htab = 0x%lx\n", htab_data.htab);
- udbg_printf("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
-
- udbg_puts("\n-----------------------------------------------------\n");
+ break;
+ case _MACH_pSeries:
+ pSeries_init_early();
+ initrd_start = initrd_end = 0;
+ parse_bootinfo();
+ break;
+ }
+ udbg_puts("\n-----------------------------------------------------\n");
+ udbg_puts("Naca Info...\n\n");
+ udbg_puts("naca = 0x");
+ udbg_puthex((unsigned long)naca);
+ udbg_putc('\n');
+
+ udbg_puts("naca->processorCount = 0x");
+ udbg_puthex(naca->processorCount);
+ udbg_putc('\n');
+
+ udbg_puts("naca->physicalMemorySize = 0x");
+ udbg_puthex(naca->physicalMemorySize);
+ udbg_putc('\n');
+
+ udbg_puts("naca->dCacheL1LineSize = 0x");
+ udbg_puthex(naca->dCacheL1LineSize);
+ udbg_putc('\n');
+
+ udbg_puts("naca->dCacheL1LogLineSize = 0x");
+ udbg_puthex(naca->dCacheL1LogLineSize);
+ udbg_putc('\n');
+
+ udbg_puts("naca->dCacheL1LinesPerPage = 0x");
+ udbg_puthex(naca->dCacheL1LinesPerPage);
+ udbg_putc('\n');
+
+ udbg_puts("naca->iCacheL1LineSize = 0x");
+ udbg_puthex(naca->iCacheL1LineSize);
+ udbg_putc('\n');
+
+ udbg_puts("naca->iCacheL1LogLineSize = 0x");
+ udbg_puthex(naca->iCacheL1LogLineSize);
+ udbg_putc('\n');
+
+ udbg_puts("naca->iCacheL1LinesPerPage = 0x");
+ udbg_puthex(naca->iCacheL1LinesPerPage);
+ udbg_putc('\n');
+
+ udbg_puts("naca->pftSize = 0x");
+ udbg_puthex(naca->pftSize);
+ udbg_putc('\n');
+
+ udbg_puts("naca->serialPortAddr = 0x");
+ udbg_puthex(naca->serialPortAddr);
+ udbg_putc('\n');
+
+ udbg_puts("naca->interrupt_controller = 0x");
+ udbg_puthex(naca->interrupt_controller);
+ udbg_putc('\n');
+
+ udbg_printf("\nHTAB Info ...\n\n");
+ udbg_puts("htab_data.htab = 0x");
+ udbg_puthex(htab_data.htab);
+ udbg_putc('\n');
+ udbg_puts("htab_data.num_ptegs = 0x");
+ udbg_puthex(htab_data.htab_num_ptegs);
+ udbg_putc('\n');
+
+ udbg_puts("\n-----------------------------------------------------\n");
+
+
+ if ( _machine & _MACH_pSeries ) {
+ finish_device_tree();
+ chrp_init(r3, r4, r5, r6, r7);
+ }
- if ( _machine == _MACH_chrp ) {
- finish_device_tree();
- chrp_init(r3, r4, r5, r6, r7);
- }
+ mm_init_ppc64();
- mm_init_ppc64();
-
- switch (_machine) {
- case _MACH_chrp: // DRENG _MACH_chrp needs to be _MACH_pSeries now
- // The following relies on the device tree being fully configured.
- parse_cmd_line(r3, r4, r5, r6, r7);
-
- break;
- case _MACH_iSeries:
- iSeries_init();
- break;
- default:
- // Need a way to die here-prob have to display something to the panel DRENG
- }
+ switch (_machine) {
+ case _MACH_iSeries:
+ iSeries_init();
+ break;
+ default:
+ /* The following relies on the device tree being */
+ /* fully configured. */
+ parse_cmd_line(r3, r4, r5, r6, r7);
+ }
}
/*
@@ -308,7 +303,7 @@
len += sprintf(len+buffer,"processor\t: %lu\n",i);
len += sprintf(len+buffer,"cpu\t\t: ");
- pvr = naca->paca[i].pvr;
+ pvr = xPaca[i].pvr;
switch (PVR_VER(pvr))
{
@@ -394,100 +389,106 @@
* Fetch the cmd_line from open firmware. */
void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7) {
- struct device_node *chosen;
- char *p;
+ struct device_node *chosen;
+ char *p;
#ifdef CONFIG_BLK_DEV_INITRD
- if (r3 && r4 && r4 != 0xdeadbeef)
- {
- if (r3 < KERNELBASE)
- r3 += KERNELBASE;
- initrd_start = r3;
- initrd_end = r3 + r4;
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- initrd_below_start_ok = 1;
+ if ((initrd_start == 0) && r3 && r4 && r4 != 0xdeadbeef) {
+ initrd_start = (r3 >= KERNELBASE) ? r3 : __va(r3);
+ initrd_end = initrd_start + r4;
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ initrd_below_start_ok = 1;
}
#endif
- cmd_line[0] = 0;
- chosen = find_devices("chosen");
- if (chosen != NULL) {
- p = get_property(chosen, "bootargs", NULL);
- if (p != NULL)
- strncpy(cmd_line, p, sizeof(cmd_line));
- }
- cmd_line[sizeof(cmd_line) - 1] = 0;
-
- /* Look for mem= option on command line */
- if (strstr(cmd_line, "mem=")) {
- char *p, *q;
- unsigned long maxmem = 0;
- extern unsigned long __max_memory;
-
- for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
- q = p + 4;
- if (p > cmd_line && p[-1] != ' ')
- continue;
- maxmem = simple_strtoul(q, &q, 0);
- if (*q == 'k' || *q == 'K') {
- maxmem <<= 10;
- ++q;
- } else if (*q == 'm' || *q == 'M') {
- maxmem <<= 20;
- ++q;
- }
- }
- __max_memory = maxmem;
- }
- ppc_md.progress("id mach: done", 0x200);
+ cmd_line[0] = 0;
+ chosen = find_devices("chosen");
+ if (chosen != NULL) {
+ p = get_property(chosen, "bootargs", NULL);
+ if (p != NULL)
+ strncpy(cmd_line, p, sizeof(cmd_line));
+ }
+ cmd_line[sizeof(cmd_line) - 1] = 0;
+
+ /* Look for mem= option on command line */
+ if (strstr(cmd_line, "mem=")) {
+ char *p, *q;
+ unsigned long maxmem = 0;
+ extern unsigned long __max_memory;
+
+ for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
+ q = p + 4;
+ if (p > cmd_line && p[-1] != ' ')
+ continue;
+ maxmem = simple_strtoul(q, &q, 0);
+ if (*q == 'k' || *q == 'K') {
+ maxmem <<= 10;
+ ++q;
+ } else if (*q == 'm' || *q == 'M') {
+ maxmem <<= 20;
+ ++q;
+ }
+ }
+ __max_memory = maxmem;
+ }
+ ppc_md.progress("id mach: done", 0x200);
+}
+
+
+char *bi_tag2str(unsigned long tag)
+{
+ switch (tag) {
+ case BI_FIRST:
+ return "BI_FIRST";
+ case BI_LAST:
+ return "BI_LAST";
+ case BI_CMD_LINE:
+ return "BI_CMD_LINE";
+ case BI_BOOTLOADER_ID:
+ return "BI_BOOTLOADER_ID";
+ case BI_INITRD:
+ return "BI_INITRD";
+ case BI_SYSMAP:
+ return "BI_SYSMAP";
+ case BI_MACHTYPE:
+ return "BI_MACHTYPE";
+ default:
+ return "BI_UNKNOWN";
+ }
}
int parse_bootinfo(void)
{
-#if 0
- /* DRENG this stuff is needs to be completly redone in the context of
- * yaboot. Remove for now - I think we can wait on this for some time.
- */
struct bi_record *rec;
- extern char __bss_start[];
extern char *sysmap;
extern unsigned long sysmap_size;
- rec = (struct bi_record *)_ALIGN((ulong)__bss_start+(1<<20)-1,(1<<20));
- if ( rec->tag != BI_FIRST )
- {
- /*
- * This 0x10000 offset is a terrible hack but it will go away when
- * we have the bootloader handle all the relocation and
- * prom calls -- Cort
- */
- rec = (struct bi_record *)_ALIGN((ulong)__bss_start+0x10000+(1<<20)-1,(1<<20));
- if ( rec->tag != BI_FIRST )
- return -1;
- }
- for ( ; rec->tag != BI_LAST ;
- rec = (struct bi_record *)((ulong)rec + rec->size) )
- {
- ulong *data = rec->data;
- switch (rec->tag)
- {
+ rec = prom.bi_recs;
+
+ if ( rec == NULL || rec->tag != BI_FIRST )
+ return -1;
+
+ for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
+ switch (rec->tag) {
case BI_CMD_LINE:
- memcpy(cmd_line, (void *)data, rec->size);
+ memcpy(cmd_line, (void *)rec->data, rec->size);
break;
case BI_SYSMAP:
- sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
- (data[0]+KERNELBASE));
- sysmap_size = data[1];
+ sysmap = (char *)((rec->data[0] >= (KERNELBASE))
+ ? rec->data[0] : __va(rec->data[0]));
+ sysmap_size = rec->data[1];
break;
#ifdef CONFIG_BLK_DEV_INITRD
case BI_INITRD:
- initrd_start = data[0];
- initrd_end = data[0] + rec->size;
+ initrd_start = __va(rec->data[0]);
+ initrd_end = initrd_start + rec->data[1];
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ initrd_below_start_ok = 1;
break;
#endif /* CONFIG_BLK_DEV_INITRD */
}
}
-#endif
+
return 0;
}
@@ -655,6 +656,21 @@
udbg_puts(" "); udbg_puthex(srr1); udbg_puts("\n");
}
+int set_spread_lpevents( char * str )
+{
+ /* The parameter is the number of processors to share in processing lp events */
+ unsigned long i;
+ unsigned long val = simple_strtoul( str, NULL, 0 );
+ if ( ( val > 0 ) && ( val <= maxPacas ) ) {
+ for ( i=1; imsr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE);
+ saved_regs[PT_SOFTE] = regs->softe;
memcpy(regs, saved_regs, GP_REGS_SIZE);
if (copy_from_user(current->thread.fpr, &sr->fp_regs,
sizeof(sr->fp_regs)))
@@ -467,6 +468,7 @@
goto badframe;
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE);
+ saved_regs[PT_SOFTE] = regs->softe;
memcpy(regs, saved_regs, GP_REGS_SIZE);
if (copy_from_user(current->thread.fpr, &sr->fp_regs,
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/signal32.c linuxppc64_2_4/arch/ppc64/kernel/signal32.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/signal32.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/signal32.c Thu Sep 13 11:54:36 2001
@@ -387,7 +387,7 @@
regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF;
regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF;
regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF;
- regs->mq = (u64)(saved_regs[PT_MQ]) & 0xFFFFFFFF;
+ /* regs->softe is left unchanged (like the MSR.EE bit) */
/******************************************************/
/* the DAR and the DSISR are only relevant during a */
/* data or instruction storage interrupt. The value */
@@ -505,7 +505,9 @@
|| __copy_to_user(&frame->gp_regs[PT_LNK], (u32*)(®s->gpr[PT_LNK])+1, sizeof(u32))
|| __copy_to_user(&frame->gp_regs[PT_XER], (u32*)(®s->gpr[PT_XER])+1, sizeof(u32))
|| __copy_to_user(&frame->gp_regs[PT_CCR], (u32*)(®s->gpr[PT_CCR])+1, sizeof(u32))
+# if 0
|| __copy_to_user(&frame->gp_regs[PT_MQ], (u32*)(®s->gpr[PT_MQ])+1, sizeof(u32))
+#endif
|| __copy_to_user(&frame->gp_regs[PT_RESULT], (u32*)(®s->gpr[PT_RESULT])+1,
sizeof(u32)))
goto badframe;
@@ -715,7 +717,7 @@
regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF;
regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF;
regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF;
- regs->mq = (u64)(saved_regs[PT_MQ]) & 0xFFFFFFFF;
+ /* regs->softe is left unchanged (like MSR.EE) */
/******************************************************/
/* the DAR and the DSISR are only relevant during a */
/* data or instruction storage interrupt. The value */
@@ -1197,7 +1199,6 @@
|| __copy_to_user(&frame->gp_regs[PT_LNK], (u32*)(®s->gpr[PT_LNK])+1, sizeof(u32))
|| __copy_to_user(&frame->gp_regs[PT_XER], (u32*)(®s->gpr[PT_XER])+1, sizeof(u32))
|| __copy_to_user(&frame->gp_regs[PT_CCR], (u32*)(®s->gpr[PT_CCR])+1, sizeof(u32))
- || __copy_to_user(&frame->gp_regs[PT_MQ], (u32*)(®s->gpr[PT_MQ])+1, sizeof(u32))
|| __copy_to_user(&frame->gp_regs[PT_RESULT], (u32*)(®s->gpr[PT_RESULT])+1,
sizeof(u32)))
goto badframe;
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/smp.c linuxppc64_2_4/arch/ppc64/kernel/smp.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/smp.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/smp.c Thu Sep 13 11:54:36 2001
@@ -45,10 +45,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include "open_pic.h"
+#include
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
@@ -79,19 +81,6 @@
extern struct Naca *naca;
extern struct Paca xPaca[];
-/* Forward declarations */
-static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait);
-static int smp_iSeries_probe(void);
-static void smp_iSeries_kick_cpu(int nr);
-static void smp_iSeries_setup_cpu(int nr);
-
-static void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait);
-static int smp_chrp_probe(void);
-static void smp_chrp_kick_cpu(int nr);
-static void smp_chrp_setup_cpu(int cpu_nr);
-
-static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait);
-static int smp_xics_probe(void);
void xics_setup_cpu(void);
void xics_cause_IPI(int cpu);
@@ -101,43 +90,10 @@
volatile unsigned long xics_ipi_message[NR_CPUS] = {0};
#define smp_message_pass(t,m,d,w) \
- do { if (smp_ops) \
- atomic_inc(&ipi_sent); \
- smp_ops->message_pass((t),(m),(d),(w)); \
+ do { atomic_inc(&ipi_sent); \
+ ppc_md.smp_message_pass((t),(m),(d),(w)); \
} while(0)
-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;
-
-/* iSeries (iSeries) */
-static struct smp_ops_t iSeries_smp_ops = {
- smp_iSeries_message_pass,
- smp_iSeries_probe,
- smp_iSeries_kick_cpu,
- smp_iSeries_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,
-};
-
-/* 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_chrp_setup_cpu,
-};
-
#ifdef CONFIG_KDB
void smp_kdb_stop(void)
{
@@ -220,6 +176,16 @@
{
}
+/* This is called very early. */
+void smp_init_iSeries(void)
+{
+ ppc_md.smp_message_pass = smp_iSeries_message_pass;
+ ppc_md.smp_probe = smp_iSeries_probe;
+ ppc_md.smp_kick_cpu = smp_iSeries_kick_cpu;
+ ppc_md.smp_setup_cpu = smp_iSeries_setup_cpu;
+}
+
+
static void
smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
{
@@ -254,7 +220,7 @@
}
static void
-smp_chrp_kick_cpu(int nr)
+smp_kick_cpu(int nr)
{
/* Verify we have a Paca for processor nr */
if ( ( nr <= 0 ) ||
@@ -335,14 +301,21 @@
return naca->processorCount;
}
-#if 0
-static void
-smp_xics_setup_cpu(int cpu_nr)
+/* This is called very early */
+void smp_init_pSeries(void)
{
- if (cpu_nr > 0)
- xics_setup_cpu();
+ if(naca->interrupt_controller == IC_OPEN_PIC) {
+ ppc_md.smp_message_pass = smp_openpic_message_pass;
+ ppc_md.smp_probe = smp_chrp_probe;
+ ppc_md.smp_kick_cpu = smp_kick_cpu;
+ ppc_md.smp_setup_cpu = smp_chrp_setup_cpu;
+ } else {
+ ppc_md.smp_message_pass = smp_xics_message_pass;
+ ppc_md.smp_probe = smp_xics_probe;
+ ppc_md.smp_kick_cpu = smp_kick_cpu;
+ ppc_md.smp_setup_cpu = smp_chrp_setup_cpu;
+ }
}
-#endif
void smp_local_timer_interrupt(struct pt_regs * regs)
@@ -481,13 +454,13 @@
#ifdef CONFIG_XMON
xmon(0);
#endif
+#ifdef CONFIG_PPC_ISERIES
+ HvCall_terminateMachineSrc();
+#endif
goto out;
}
barrier();
udelay(1);
-#ifdef CONFIG_PPC_ISERIES
- HvCallCfg_getLps();
-#endif
}
if (wait) {
@@ -497,13 +470,13 @@
if (--timeout == 0) {
printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n",
smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started));
+#ifdef CONFIG_PPC_ISERIES
+ HvCall_terminateMachineSrc();
+#endif
goto out;
}
barrier();
udelay(1);
-#ifdef CONFIG_PPC_ISERIES
- HvCallCfg_getLps();
-#endif
}
}
ret = 0;
@@ -576,7 +549,7 @@
init_idle();
for (i = 0; i < NR_CPUS; i++) {
- paca = &(naca->paca[i]);
+ paca = &xPaca[i];
paca->prof_counter=1;
paca->prof_multiplier = 1;
if(i != 0) {
@@ -590,7 +563,6 @@
paca->xStab_data.virt = (unsigned long)&stab_array[PAGE_SIZE * (i-1)];
arpn = physRpn_to_absRpn(___pa(paca->xStab_data.virt) >> 12);
paca->xStab_data.real = arpn << 12;
- paca->xHwProcNum = cpu_hw_index[i];
memset((void *)paca->xStab_data.virt, 0, PAGE_SIZE);
paca->default_decr = tb_ticks_per_jiffy / decr_overclock;
}
@@ -605,24 +577,8 @@
*/
cacheflush_time = 5 * 1024;
- switch ( _machine ) {
- case _MACH_chrp:
- if (OpenPIC_Addr) {
- smp_ops = &chrp_smp_ops;
- } else {
- smp_ops = &xics_smp_ops;
- }
- break;
- case _MACH_iSeries:
- smp_ops = &iSeries_smp_ops;
- break;
- default:
- printk("SMP not supported on this machine.\n");
- return;
- }
-
/* Probe arch for CPUs */
- cpu_nr = smp_ops->probe();
+ cpu_nr = ppc_md.smp_probe();
printk("Probe found %d CPUs\n", cpu_nr);
@@ -680,7 +636,7 @@
current_set[i].sp_real);
/* wake up cpus */
- smp_ops->kick_cpu(i);
+ ppc_md.smp_kick_cpu(i);
/*
* wait to see if the cpu made a callin (is actually up).
@@ -688,9 +644,6 @@
* -- Cort
*/
for ( c = 5000; c && !cpu_callin_map[i] ; c-- ) {
-#ifdef CONFIG_PPC_ISERIES
- HvCallCfg_getLps();
-#endif
udelay(100);
}
@@ -707,7 +660,7 @@
}
/* Setup CPU 0 last (important) */
- smp_ops->setup_cpu(0);
+ ppc_md.smp_setup_cpu(0);
if (smp_num_cpus < 2)
smp_tb_synchronized = 1;
@@ -731,7 +684,7 @@
set_dec(xPaca[cpu].default_decr);
cpu_callin_map[cpu] = 1;
- smp_ops->setup_cpu(cpu);
+ ppc_md.smp_setup_cpu(cpu);
init_idle();
@@ -745,9 +698,6 @@
cpu_callin_map[cpu] = 1;
while(!smp_commenced) {
-#ifdef CONFIG_PPC_ISERIES
- HvCallCfg_getLps();
-#endif
barrier();
}
__sti();
@@ -785,7 +735,7 @@
*/
void __init smp_store_cpu_info(int id)
{
- naca->paca[id].pvr = _get_PVR();
+ xPaca[id].pvr = _get_PVR();
}
static int __init maxcpus(char *str)
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/stab.c linuxppc64_2_4/arch/ppc64/kernel/stab.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/stab.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/stab.c Sat Sep 15 23:15:49 2001
@@ -20,53 +20,34 @@
inline int make_ste(unsigned long stab,
unsigned long esid, unsigned long vsid);
inline void make_slbe(unsigned long esid, unsigned long vsid);
-extern unsigned long reloc_offset(void);
extern struct Naca *naca;
/*
- * Initialize the segment table for this processor with the set
- * of kernel addresses.
+ * Initialize the segment table for this processor. We fault in all
+ * entries except the first kernel segment.
*/
+void stab_initialize(unsigned long skip_esid_c, unsigned long stab)
+{
+ unsigned long esid, vsid;
-void
-stab_initialize(unsigned long skip_esid_c, unsigned long stab) {
- unsigned long offset = reloc_offset();
- unsigned long esid, last_esid, vsid;
-
- /*
- * Put in STEs for the 0xC00000000 - 0xF00000000 segments.
- */
esid = GET_ESID(KERNELBASE);
+ vsid = get_kernel_vsid(esid << SID_SHIFT);
- /*
- * If asked to skip loading esid 0xC00000000 then skip it.
- */
- if ( skip_esid_c )
- esid += (REGION_STRIDE >> SID_SHIFT);
+ if (skip_esid_c)
+ return;
- /*
- * Put entries into the STAB for the first segment of the 4 kernel
- * regions (0xC - 0xF). These are left in the table during flush.
- * All other kernel segments (including bolted) are demand faulted.
- */
- last_esid = GET_ESID(KERNELBASE) + (2 * (REGION_STRIDE >> SID_SHIFT));
-
- for (; esid <= last_esid; esid += (REGION_STRIDE >> SID_SHIFT)) {
- /* Map the esid to an EA & find the vsid we need. */
- vsid = get_kernel_vsid(esid << SID_SHIFT);
- if(!__is_processor(PV_POWER4)) {
- make_ste(stab, esid, vsid);
- } else {
- make_slbe(esid, vsid );
- }
- }
+ if (!__is_processor(PV_POWER4))
+ make_ste(stab, esid, vsid);
+ else
+ make_slbe(esid, vsid);
}
/*
* Create a segment table entry for the given esid/vsid pair.
*/
inline int
-make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) {
+make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
+{
unsigned long entry, group, old_esid, castout_entry, i;
unsigned int global_entry;
STE *ste, *castout_ste;
@@ -101,7 +82,7 @@
/*
* Could not find empty entry, pick one with a round robin selection.
* Search all entries in the two groups. Note that the first time
- * we get here, we start with entry REGION_COUNT - 1 so the initializer
+ * we get here, we start with entry 1 so the initializer
* can be common with the SLB castout code.
*/
@@ -155,7 +136,8 @@
/*
* Create a segment buffer entry for the given esid/vsid pair.
*/
-inline void make_slbe(unsigned long esid, unsigned long vsid) {
+inline void make_slbe(unsigned long esid, unsigned long vsid)
+{
unsigned long entry, castout_entry;
slb_dword0 castout_esid_data;
union {
@@ -212,7 +194,7 @@
entry = castout_entry;
castout_entry++;
if(castout_entry >= naca->slb_size) {
- castout_entry = REGION_COUNT - 1;
+ castout_entry = 1;
}
get_paca()->xStab_data.next_round_robin = castout_entry;
@@ -246,6 +228,7 @@
unsigned long trap)
{
unsigned long vsid, esid;
+ int kernel_segment = 0;
PMC_SW_PROCESSOR(stab_faults);
@@ -256,6 +239,7 @@
/* Kernel or user address? */
if (REGION_ID(ea) >= KERNEL_REGION_ID) {
+ kernel_segment = 1;
vsid = get_kernel_vsid( ea );
} else {
struct mm_struct *mm = current->mm;
@@ -277,7 +261,7 @@
segments = get_paca()->xSegments;
top_entry = segments[0];
- if(top_entry < (STAB_CACHE_SIZE - 1)) {
+ if(!kernel_segment && top_entry < (STAB_CACHE_SIZE - 1)) {
top_entry++;
segments[top_entry] = stab_entry;
if(top_entry == STAB_CACHE_SIZE - 1) top_entry = 0xff;
@@ -293,11 +277,15 @@
* Kernel and Bolted entries are not removed as we cannot tolerate
* faults on those addresses.
*/
-void flush_stab(void) {
+
+#define STAB_PRESSURE 0
+
+void flush_stab(void)
+{
STE *stab = (STE *) get_paca()->xStab_data.virt;
unsigned char *segments = get_paca()->xSegments;
unsigned long flags, i;
-
+
if(!__is_processor(PV_POWER4)) {
unsigned long entry;
STE *ste;
@@ -306,7 +294,7 @@
__asm__ __volatile__ ("isync" : : : "memory");
__save_and_cli(flags);
- if(segments[0] != 0xff) {
+ if(segments[0] != 0xff && !STAB_PRESSURE) {
for(i = 1; i <= segments[0]; i++) {
ste = stab + segments[i];
ste->dw0.dw0.v = 0;
@@ -316,13 +304,17 @@
/* Invalidate all entries. */
ste = stab;
- /* Never flush the first four entries. */
- ste += 4;
- for(entry = 4;
+ /* Never flush the first entry. */
+ ste += 1;
+ for(entry = 1;
entry < (PAGE_SIZE / sizeof(STE));
entry++, ste++) {
- ste->dw0.dw0.v = 0;
- PMC_SW_PROCESSOR(stab_invalidations);
+ unsigned long ea;
+ ea = ste->dw0.dw0.esid << SID_SHIFT;
+ if (STAB_PRESSURE || ea < KERNELBASE) {
+ ste->dw0.dw0.v = 0;
+ PMC_SW_PROCESSOR(stab_invalidations);
+ }
}
}
@@ -337,33 +329,13 @@
/* Force flush to complete. */
__asm__ __volatile__ ("sync" : : : "memory");
} else {
- /* Invalidate the entire SLB (except entry 1), and then put */
- /* back in the bolted range translation. */
- /* This only does the first bolted segment presently. DRENG */
unsigned long msr, tmp;
-
- /* esid v idx */
- slb_dword0 esid_data = {GET_ESID(BOLTEDBASE), 1, 0, 1};
-
- /* vsid ks kp */
- slb_dword1 vsid_data = {0, 0, 1, 0, 0, 0, 0};
- vsid_data.vsid = get_kernel_vsid(BOLTEDBASE);
+ unsigned long flags;
PMC_SW_PROCESSOR(stab_invalidations);
- __asm__ __volatile__("\n\
- mfmsr %0 \n\
- rldicl %1,%0,48,1 \n\
- rldicl %1,%1,16,0 \n\
- mtmsrd %1 \n\
- isync \n\
- slbia \n\
- isync \n\
- slbmte %2,%3 \n\
- isync \n\
- mtmsrd %0"
- : "=&r"(msr), "=&r"(tmp)
- : "r" (vsid_data), "r" (esid_data)
- : "memory");
+ __save_and_cli(flags);
+ __asm__ __volatile__("isync; slbia; isync":::"memory");
+ __restore_flags(flags);
}
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/time.c linuxppc64_2_4/arch/ppc64/kernel/time.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/time.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/time.c Sat Sep 15 22:42:59 2001
@@ -25,21 +25,6 @@
* non ambiguous timestamps even around leap seconds. This needs
* a new timestamp format and a good name.
*
- *
- * The following comment is partially obsolete (at least the long wait
- * is no more a valid reason):
- * Since the MPC8xx has a programmable interrupt timer, I decided to
- * use that rather than the decrementer. Two reasons: 1.) the clock
- * frequency is low, causing 2.) a long wait in the timer interrupt
- * while ((d = get_dec()) == dval)
- * loop. The MPC8xx can be driven from a variety of input clocks,
- * so a number of assumptions have been made here because the kernel
- * parameter HZ is a constant. We assume (correctly, today :-) that
- * the MPC8xx on the MBX board is driven from a 32.768 kHz crystal.
- * This is then divided by 4, providing a 8192 Hz clock into the PIT.
- * Since it is not possible to get a nice 100 Hz clock out of this, without
- * creating a software PLL, I have set HZ to 128. -- Dan
- *
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
* "A Kernel Model for Precision Timekeeping" by Dave Mills
*
@@ -182,6 +167,11 @@
if (!user_mode(regs))
ppc_do_profile(instruction_pointer(regs));
+ /* We need to clear the decrementer interrupt pending flag
+ * before setting the new decrementer below
+ */
+ paca->xLpPaca.xIntDword.xFields.xDecrInt = 0;
+
while ( paca->next_jiffy_update_tb <= (cur_tb = get_tb()) ) {
#ifdef CONFIG_SMP
@@ -195,6 +185,7 @@
}
paca->next_jiffy_update_tb += tb_ticks_per_jiffy;
}
+
next_dec = paca->next_jiffy_update_tb - cur_tb;
if ( next_dec > paca->default_decr )
next_dec = paca->default_decr;
@@ -203,9 +194,8 @@
if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
ppc_md.heartbeat();
- paca->xLpPaca.xIntDword.xFields.xDecrInt = 0;
lpq = paca->lpQueuePtr;
- if ( lpq )
+ if ( lpq && ItLpQueue_isLpIntPending( lpq ) )
lpEvent_count += ItLpQueue_process( lpq, regs );
irq_exit(cpu);
@@ -222,7 +212,8 @@
void do_gettimeofday(struct timeval *tv)
{
unsigned long flags;
- unsigned long delta, lost_ticks, usec, sec;
+ unsigned long lost_ticks, sec;
+ long delta, usec;
read_lock_irqsave(&xtime_lock, flags);
sec = xtime.tv_sec;
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/traps.c linuxppc64_2_4/arch/ppc64/kernel/traps.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/traps.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/traps.c Fri Sep 14 22:04:33 2001
@@ -115,11 +115,6 @@
{
if ( !user_mode(regs) )
{
-#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
- /* the qspan pci read routines can cause machine checks -- Cort */
- bad_page_fault(regs, regs->dar);
- return;
-#endif
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_fault_handler) {
debugger_fault_handler(regs);
@@ -191,7 +186,7 @@
}
void
-InstructionBreakpoint(struct pt_regs *regs)
+InstructionBreakpointException(struct pt_regs *regs)
{
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
if (debugger_iabr_match(regs))
@@ -205,31 +200,8 @@
}
void
-RunModeException(struct pt_regs *regs)
-{
- _exception(SIGTRAP, regs);
-}
-
-void
ProgramCheckException(struct pt_regs *regs)
{
-#if defined(CONFIG_4xx)
- unsigned int esr = mfspr(SPRN_ESR);
-
- if (esr & ESR_PTR) {
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
- if (debugger_bpt(regs))
- return;
-#endif
-#ifdef CONFIG_KDB
- if (kdb(KDB_REASON_BREAK, 0, regs))
- return;
-#endif
- _exception(SIGTRAP, regs);
- } else {
- _exception(SIGILL, regs);
- }
-#else
if (regs->msr & 0x100000) {
/* IEEE FP exception */
_exception(SIGFPE, regs);
@@ -247,7 +219,6 @@
} else {
_exception(SIGILL, regs);
}
-#endif
}
void
@@ -319,48 +290,6 @@
printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n",
current, current->pid, regs->nip, regs->link, regs->gpr[0],
regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
-}
-
-#ifdef CONFIG_8xx
-void
-SoftwareEmulation(struct pt_regs *regs)
-{
- extern int do_mathemu(struct pt_regs *);
- int errcode;
-
- if (!user_mode(regs)) {
- show_regs(regs);
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
- debugger(regs);
-#endif
-#ifdef CONFIG_KDB
- if (kdb(KDB_REASON_FAULT, 0, regs))
- return ;
-#endif
- print_backtrace((unsigned long *)regs->gpr[1]);
- panic("Kernel Mode Software FPU Emulation");
- }
-
-#ifdef CONFIG_MATH_EMULATION
- if ((errcode = do_mathemu(regs))) {
-#else
- if ((errcode = Soft_emulate_8xx(regs))) {
-#endif
- if (errcode > 0)
- _exception(SIGFPE, regs);
- else if (errcode == -EFAULT)
- _exception(SIGSEGV, regs);
- else
- _exception(SIGILL, regs);
- }
-}
-#endif
-
-void
-TAUException(struct pt_regs *regs)
-{
- printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n",
- regs->nip, regs->msr, regs->trap);
}
void __init trap_init(void)
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/udbg.c linuxppc64_2_4/arch/ppc64/kernel/udbg.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/udbg.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/udbg.c Wed Sep 5 13:56:40 2001
@@ -21,6 +21,7 @@
#define WANT_PPCDBG_TAB /* Only defined here */
#include
#include
+#include
extern struct Naca *naca;
extern int _machine;
@@ -52,24 +53,24 @@
#define LSR_TEMT 0x40 /* Xmitter empty */
#define LSR_ERR 0x80 /* Error */
-void *comport1;
+volatile struct NS16550 *udbg_comport;
static inline void eieio(void) { asm volatile ("eieio" : :); }
void
-udbg_init(void)
+udbg_init_uart(void *comport)
{
- if ( _machine != _MACH_iSeries ) {
- volatile struct NS16550 *port = (struct NS16550 *)comport1;
- port->lcr = 0x00; eieio();
- port->ier = 0xFF; eieio();
- port->ier = 0x00; eieio();
- port->lcr = 0x80; eieio(); /* Access baud rate */
- port->dll = 12; eieio(); /* 1 = 115200, 2 = 57600, 3 = 38400, 12 = 9600 baud */
- port->dlm = 0; eieio(); /* dll >> 8 which should be zero for fast rates; */
- port->lcr = 0x03; eieio(); /* 8 data, 1 stop, no parity */
- port->mcr = 0x03; eieio(); /* RTS/DTR */
- port->fcr = 0x07; eieio(); /* Clear & enable FIFOs */
+ if (comport) {
+ udbg_comport = (struct NS16550 *)comport;
+ udbg_comport->lcr = 0x00; eieio();
+ udbg_comport->ier = 0xFF; eieio();
+ udbg_comport->ier = 0x00; eieio();
+ udbg_comport->lcr = 0x80; eieio(); /* Access baud rate */
+ udbg_comport->dll = 12; eieio(); /* 1 = 115200, 2 = 57600, 3 = 38400, 12 = 9600 baud */
+ udbg_comport->dlm = 0; eieio(); /* dll >> 8 which should be zero for fast rates; */
+ udbg_comport->lcr = 0x03; eieio(); /* 8 data, 1 stop, no parity */
+ udbg_comport->mcr = 0x03; eieio(); /* RTS/DTR */
+ udbg_comport->fcr = 0x07; eieio(); /* Clear & enable FIFOs */
}
}
@@ -77,32 +78,40 @@
void
udbg_putc(unsigned char c)
{
- if ( _machine != _MACH_iSeries ) {
- volatile struct NS16550 *port = (struct NS16550 *)comport1;
- while ((port->lsr & LSR_THRE) == 0)
- /* wait for idle */;
- port->thr = c; eieio();
- if (c == '\n') {
- /* Also put a CR. This is for convenience. */
- while ((port->lsr & LSR_THRE) == 0)
- /* wait for idle */;
- port->thr = '\r'; eieio();
- }
- }
- else {
- printk("%c", c);
- }
+ if ( udbg_comport ) {
+ while ((udbg_comport->lsr & LSR_THRE) == 0)
+ /* wait for idle */;
+ udbg_comport->thr = c; eieio();
+ if (c == '\n') {
+ /* Also put a CR. This is for convenience. */
+ while ((udbg_comport->lsr & LSR_THRE) == 0)
+ /* wait for idle */;
+ udbg_comport->thr = '\r'; eieio();
+ }
+ } else if ( _machine == _MACH_iSeries ) {
+ /* ToDo: switch this via ppc_md */
+ printk("%c", c);
+ }
+}
+int udbg_getc_poll(void)
+{
+ if ( udbg_comport ) {
+ if ((udbg_comport->lsr & LSR_DR) != 0)
+ return udbg_comport->rbr;
+ else
+ return -1;
+ }
+ return -1;
}
unsigned char
udbg_getc(void)
{
- if ( _machine != _MACH_iSeries ) {
- volatile struct NS16550 *port = (struct NS16550 *)comport1;
- while ((port->lsr & LSR_DR) == 0)
+ if ( udbg_comport ) {
+ while ((udbg_comport->lsr & LSR_DR) == 0)
/* wait for char */;
- return port->rbr;
+ return udbg_comport->rbr;
}
return 0;
}
@@ -110,18 +119,50 @@
void
udbg_puts(const char *s)
{
- if ( _machine != _MACH_iSeries ) {
+ if (ppc_md.udbg_putc) {
char c;
- if ( s && *s != '\0' )
+ if ( s && *s != '\0' ) {
while ( ( c = *s++ ) != '\0' )
- udbg_putc(c);
- else
+ ppc_md.udbg_putc(c);
+ } else
udbg_puts("NULL");
}
else
printk("%s", s);
}
+int
+udbg_write(const char *s, int n)
+{
+ int remain = n;
+ char c;
+ if (!ppc_md.udbg_putc)
+ for (;;); /* stop here for cpuctl */
+ if ( s && *s != '\0' ) {
+ while ( (( c = *s++ ) != '\0') && (remain-- > 0)) {
+ ppc_md.udbg_putc(c);
+ }
+ } else
+ udbg_puts("NULL");
+ return n - remain;
+}
+
+int
+udbg_read(char *buf, int buflen) {
+ char c, *p = buf;
+ int i;
+ if (!ppc_md.udbg_putc)
+ for (;;); /* stop here for cpuctl */
+ for (i = 0; i < buflen; ++i) {
+ do {
+ c = ppc_md.udbg_getc();
+ } while (c == 0x11 || c == 0x13);
+ *p++ = c;
+ }
+ return i;
+}
+
+
void
udbg_puthex(unsigned long val)
{
@@ -140,7 +181,7 @@
void
udbg_printSP(const char *s)
{
- if ( _machine != _MACH_iSeries ) {
+ if ( _machine == _MACH_pSeries ) {
unsigned long sp;
asm("mr %0,1" : "=r" (sp) :);
if (s)
@@ -167,34 +208,33 @@
void
udbg_ppcdbg(unsigned long flags, const char *fmt, ...)
{
- unsigned long active_debugs = flags & naca->debug_switch;
- if ( active_debugs ) {
- va_list ap;
- unsigned char buf[256];
- unsigned long i, len = 0;
-
- for(i=0; i < PPCDBG_NUM_FLAGS ;i++) {
- if (((1U << i) & active_debugs) &&
- trace_names[i]) {
- len += strlen(trace_names[i]);
- udbg_puts(trace_names[i]);
- break;
- }
+ unsigned long active_debugs = flags & naca->debug_switch;
+ if ( active_debugs ) {
+ va_list ap;
+ unsigned char buf[256];
+ unsigned long i, len = 0;
+ for(i=0; i < PPCDBG_NUM_FLAGS ;i++) {
+ if (((1U << i) & active_debugs) &&
+ trace_names[i]) {
+ len += strlen(trace_names[i]);
+ udbg_puts(trace_names[i]);
+ break;
}
- sprintf(buf, " [%s]: ", current->comm);
- len += strlen(buf);
- udbg_puts(buf);
-
- while(len < 18) {
- udbg_putc(' ');
- len++;
- }
-
- va_start(ap, fmt);
- vsprintf(buf, fmt, ap);
- udbg_puts(buf);
- va_end(ap);
}
+ sprintf(buf, " [%s]: ", current->comm);
+ len += strlen(buf);
+ udbg_puts(buf);
+
+ while(len < 18) {
+ udbg_puts(" ");
+ len++;
+ }
+
+ va_start(ap, fmt);
+ vsprintf(buf, fmt, ap);
+ udbg_puts(buf);
+ va_end(ap);
+ }
}
unsigned long
@@ -210,7 +250,6 @@
void
udbg_dump(char *msg, void *addr, unsigned len)
{
- if ( _machine != _MACH_iSeries ) {
int i;
int j;
int numrows;
@@ -218,48 +257,49 @@
unsigned char tc;
char *buff = addr;
- if (msg) {
- udbg_puts(msg);
- udbg_puts("\n");
- }
-
- if (!buff) {
- udbg_puts(" Danger, Will Robinson, Null Pointer\n");
- return;
- }
- numrows = (len + 15) / 16;
-
- for (i = 0; i < numrows; i++) {
- udbg_printf("%016lx ", &buff[i*16]);
- for (j = 0; j < 16; j++) {
- if (j + i * 16 >= len) {
- udbg_puts(" ");
- } else {
- udbg_printf("%02x", (unsigned char)buff[j + i * 16]);
- } /* endif */
- if (j % 8 == 7) {
- udbg_puts(" ");
- } /* endif */
- } /* endfor */
-
- udbg_puts(" a|");
-
- for (j = 0; j < 16; j++) {
- if (j + i * 16 >= len) {
- udbg_putc(' ');
- } else {
- c = (unsigned char)buff[j + i * 16];
- tc = c;
- if (tc >= 32 && tc < 127 && tc != ' ') {
- udbg_putc(tc);
- } else {
- udbg_putc('.');
- } /* endif */
- } /* endif */
- } /* endfor */
- udbg_putc('|');
- udbg_putc('\n');
- } /* endfor */
+ if ( _machine == _MACH_pSeries ) {
+ if (msg) {
+ udbg_puts(msg);
+ udbg_puts("\n");
+ }
+
+ if (!buff) {
+ udbg_puts(" Danger, Will Robinson, Null Pointer\n");
+ return;
+ }
+ numrows = (len + 15) / 16;
+
+ for (i = 0; i < numrows; i++) {
+ udbg_printf("%016lx ", &buff[i*16]);
+ for (j = 0; j < 16; j++) {
+ if (j + i * 16 >= len) {
+ udbg_puts(" ");
+ } else {
+ udbg_printf("%02x", (unsigned char)buff[j + i * 16]);
+ } /* endif */
+ if (j % 8 == 7) {
+ udbg_puts(" ");
+ } /* endif */
+ } /* endfor */
+
+ udbg_puts(" a|");
+
+ for (j = 0; j < 16; j++) {
+ if (j + i * 16 >= len) {
+ ppc_md.udbg_putc(' ');
+ } else {
+ c = (unsigned char)buff[j + i * 16];
+ tc = c;
+ if (tc >= 32 && tc < 127 && tc != ' ') {
+ ppc_md.udbg_putc(tc);
+ } else {
+ ppc_md.udbg_putc('.');
+ } /* endif */
+ } /* endif */
+ } /* endfor */
+ ppc_md.udbg_putc('|');
+ ppc_md.udbg_putc('\n');
+ } /* endfor */
}
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/viopath.c linuxppc64_2_4/arch/ppc64/kernel/viopath.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/viopath.c Thu Sep 6 14:05:10 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/viopath.c Wed Dec 31 18:00:00 1969
@@ -1,711 +0,0 @@
-/*
- * arch/ppc64/viopath.c
- *
- * iSeries Virtual I/O Message Path code
- *
- * Author: Dave Boutcher
- * (C) Copyright 2000 IBM Corporation
- *
- * 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) anyu later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef _HVLPEVENT_H
-#include
-#endif
-#ifndef _HVLPConfig_H
-#include
-#endif
-#ifndef _HVCallCfg_H
-#include
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#ifndef _VIO_H
-#include
-#endif
-#ifndef _MF_H
-#include
-#endif
-#ifndef _ISERIES_PROC_H
-#include
-#endif
-
-/* Status of the path to each other partition in the system.
- * This is overkill, since we will only ever establish connections
- * to our hosting partition and the primary partition on the system.
- * But this allows for other support in the future.
- */
-static struct viopathStatus {
- int isOpen:1; /* Did we open the path? */
- int isActive:1; /* Do we have a mon msg outstanding */
-#if defined(CONFIG_VIOCONS)
- int xCharUsers;
-#endif
-#if defined(CONFIG_VIODASD)
- int xBlockUsers;
-#endif
-#if defined(CONFIG_VIOCD)
- int xCDUsers;
-#endif
-#if defined(CONFIG_VIOTAPE)
- int xTapeUsers;
-#endif
- int xConfigUsers;
- HvLpInstanceId mSourceInst;
- HvLpInstanceId mTargetInst;
- int numberAllocated;
- spinlock_t statuslock;
- unsigned long statuslockFlags;
-} viopathStatus[HVMAXARCHITECTEDLPS];
-
-/* We use this structure to handle asynchronous responses. The caller
- * blocks on the semaphore and the handler posts the semaphore.
- */
-struct doneAllocParms_t {
- struct semaphore *sem;
- int number;
-};
-
-/* Put a sequence number in each mon msg. The value is not
- * important. Start at something other than 0 just for
- * readability. wrapping this is ok.
- */
-static u8 viomonseq = 22;
-
-/* Our hosting logical partition. We get this at startup
- * time, and different modules access this variable directly.
- */
-HvLpIndex viopath_hostLp;
-
-/* For each kind of incoming event we set a pointer to a
- * routine to call.
- */
-static vio_event_handler_t *vio_handleCharEvent;
-static vio_event_handler_t *vio_handleBlockEvent;
-static vio_event_handler_t *vio_handleCDEvent;
-static vio_event_handler_t *vio_handleTapeEvent;
-
-/*
- * For each kind of event we allocate a buffer that is
- * guaranteed not to cross a page boundary
- */
-void * vio_char_event_buffer;
-void * vio_block_event_buffer;
-void * vio_cd_event_buffer;
-void * vio_tape_event_buffer;
-
-/***************************************************************************
- * A page to build an lp event in
- ***************************************************************************/
-unsigned long VIOReqPage;
-
-/***************************************************************************
- * Handle reads from the proc file system
- ***************************************************************************/
-static int proc_read(char *buf, char **start, off_t offset,
- int blen, int *eof, void *data)
-{
- HvLpEvent_Rc hvrc;
- DECLARE_MUTEX_LOCKED(Semaphore);
- dma_addr_t dmaa = pci_map_single( NULL, buf, PAGE_SIZE, PCI_DMA_FROMDEVICE);
- int len = PAGE_SIZE;
-
- if (len > blen)
- len = blen;
-
- memset(buf,0x00,len);
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_config | vioconfigget,
- HvLpEvent_AckInd_DoAck,
- HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64)(unsigned long)&Semaphore,
- VIOVERSION << 16,
- ((u64)dmaa) << 32,
- len,
- 0,
- 0);
- if (hvrc != HvLpEvent_Rc_Good)
- {
- printk("viopath hv error on op %d\n",(int)hvrc);
- }
-
- down(&Semaphore);
-
- pci_unmap_single( NULL, dmaa, PAGE_SIZE, PCI_DMA_FROMDEVICE);
-
- *eof = 1;
- return strlen(buf);
-}
-
-/***************************************************************************
- * Handle writes to our proc file system
- ***************************************************************************/
-static int proc_write(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- printk("viopath: in proc_write, got %ld bytes starting with %c\n",
- count, buffer[0]);
- return count;
-}
-
-/***************************************************************************
- * setup our proc file system entries
- ***************************************************************************/
-void vio_proc_init(struct proc_dir_entry *iSeries_proc)
-{
- struct proc_dir_entry *ent;
- ent = create_proc_entry("config", S_IFREG|S_IRUSR, iSeries_proc);
- if (!ent) return;
- ent->nlink = 1;
- ent->data = NULL;
- ent->read_proc = proc_read;
- ent->write_proc = proc_write;
-}
-
-/* Boot time initialization of the vio path code. Needs
- * to be called before any VIO components start
- */
-void viopath_init(void)
-{
- int i;
- memset(viopathStatus,0x00,sizeof(viopathStatus));
- for (i=0; ixFlags.xFunction == HvLpEvent_Function_Int)
- {
- printk("viopath: got monitor INT event\n");
- remoteLp = event->xSourceLp;
- if (!viopathStatus[remoteLp].isActive)
- sendMonMsg(remoteLp);
- }
- else
- {
- remoteLp = event->xTargetLp;
- printk("viopath: got monitor ACK event %d, sinst %d, tinst %d\n",
- (int)event->xCorrelationToken,
- event->xSourceInstanceId,
- event->xTargetInstanceId);
- /* Other partition went away! */
- if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) ||
- (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst))
- {
- printk("viopath: ignoring ack....mismatched instances\n");
- }
- else
- {
- printk("viopath: closing path %d\n",remoteLp);
-
- viopathStatus[remoteLp].isActive = 0;
-
- if (vio_handleBlockEvent!= NULL)
- (*vio_handleBlockEvent)(NULL);
-
- if (vio_handleCharEvent != NULL)
- (*vio_handleCharEvent)(NULL);
-
- if (vio_handleCDEvent != NULL)
- (*vio_handleCDEvent)(NULL);
-
- if (vio_handleTapeEvent != NULL)
- (*vio_handleTapeEvent)(NULL);
- }
- }
-}
-
-void vio_setBlockHandler(vio_event_handler_t *beh)
-{
- vio_handleBlockEvent = *beh;
-}
-
-void vio_clearBlockHandler(void)
-{
- vio_handleBlockEvent = NULL;
-}
-
-void vio_setCharHandler(vio_event_handler_t *ceh)
-{
- vio_handleCharEvent = *ceh;
-}
-
-void vio_clearCharHandler(void)
-{
- vio_handleCharEvent = NULL;
-}
-
-void vio_setCDHandler(vio_event_handler_t *ceh)
-{
- vio_handleCDEvent = *ceh;
-}
-
-void vio_clearCDHandler(void)
-{
- vio_handleCDEvent = NULL;
-}
-
-void vio_setTapeHandler(vio_event_handler_t *ceh)
-{
- vio_handleTapeEvent = *ceh;
-}
-
-void vio_clearTapeHandler(void)
-{
- vio_handleTapeEvent = NULL;
-}
-
-static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
-{
- HvLpIndex remoteLp;
- if (event->xFlags.xFunction == HvLpEvent_Function_Int)
- {
- remoteLp = event->xSourceLp;
- if (event->xSourceInstanceId != viopathStatus[remoteLp].mTargetInst)
- {
- printk("viopath: int msg rcvd, source inst (%d) doesnt match (%d)\n",
- viopathStatus[remoteLp].mTargetInst,
- event->xSourceInstanceId);
- return;
- }
-
- if (event->xTargetInstanceId != viopathStatus[remoteLp].mSourceInst)
- {
- printk("viopath: int msg rcvd, target inst (%d) doesnt match (%d)\n",
- viopathStatus[remoteLp].mSourceInst,
- event->xTargetInstanceId);
- return;
- }
- }
- else
- {
- remoteLp = event->xTargetLp;
- if (event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst)
- {
- printk("viopath: ack msg rcvd, source inst (%d) doesnt match (%d)\n",
- viopathStatus[remoteLp].mSourceInst,
- event->xSourceInstanceId);
- return;
- }
-
- if (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)
- {
- printk("viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n",
- viopathStatus[remoteLp].mTargetInst,
- event->xTargetInstanceId);
- return;
- }
- }
-
-
- switch (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) {
- case viomajorsubtype_config:
- up((struct semaphore *)event->xCorrelationToken);
- break;
-
- case viomajorsubtype_monitor:
- handleMonitorEvent(event);
- break;
- case viomajorsubtype_blockio:
- if (vio_handleBlockEvent)
- {
- (*vio_handleBlockEvent)(event);
- }
- else
- {
- printk("vio: unexpected virtual blockio event\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)
- {
- event->xRc = HvLpEvent_Rc_InvalidSubtype;
- HvCallEvent_ackLpEvent(event);
- }
- }
- break;
- case viomajorsubtype_chario:
- if (vio_handleCharEvent)
- {
- (*vio_handleCharEvent)(event);
- }
- else
- {
- printk("vio: unexpected virtual chario event\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)
- {
- event->xRc = HvLpEvent_Rc_InvalidSubtype;
- HvCallEvent_ackLpEvent(event);
- }
- }
- break;
- case viomajorsubtype_cdio:
- if (vio_handleCDEvent)
- {
- (*vio_handleCDEvent)(event);
- }
- else
- {
- printk("vio: unexpected virtual cd event\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)
- {
- event->xRc = HvLpEvent_Rc_InvalidSubtype;
- HvCallEvent_ackLpEvent(event);
- }
- }
- break;
- case viomajorsubtype_tape:
- if (vio_handleTapeEvent)
- {
- (*vio_handleTapeEvent)(event);
- }
- else
- {
- printk("vio: unexpected virtual tape event\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)
- {
- event->xRc = HvLpEvent_Rc_InvalidSubtype;
- HvCallEvent_ackLpEvent(event);
- }
- }
- break;
- default:
- printk("vio: unexpected virtual io event subtype %d\n",event->xSubtype);
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)
- {
- event->xRc = HvLpEvent_Rc_InvalidSubtype;
- HvCallEvent_ackLpEvent(event);
- }
- }
-}
-
-
-static void viopath_donealloc(void *parm, int number)
-{
- struct doneAllocParms_t *doneAllocParmsp = (struct doneAllocParms_t *)parm;
- doneAllocParmsp->number = number;
- up(doneAllocParmsp->sem);
-}
-
-int viopath_open(HvLpIndex remoteLp, int subtype)
-{
- HvLpEvent_Rc hvrc;
- struct doneAllocParms_t doneAllocParms;
- DECLARE_MUTEX_LOCKED(Semaphore);
-
- if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
- return -EINVAL;
-
- if (VIOReqPage == 0)
- {
- /* Get a page to build read/write LP events in */
- VIOReqPage = get_free_page(GFP_KERNEL);
- if (!VIOReqPage)
- {
- printk("viopath: error allocating I/O memory\n");
- return -ENOMEM;
- }
-
- vio_char_event_buffer = (void *)VIOReqPage;
- vio_block_event_buffer = (void *)(VIOReqPage+256);
- vio_cd_event_buffer = (void *)(VIOReqPage+512);
- vio_tape_event_buffer = (void *)(VIOReqPage+768);
- }
-
- if ( (0)
-#if defined(CONFIG_VIODASD)
- || (subtype == viomajorsubtype_blockio)
-#endif
-#if defined(CONFIG_VIOCONS)
- || (subtype == viomajorsubtype_chario)
-#endif
-#if defined(CONFIG_VIOCD)
- || (subtype == viomajorsubtype_cdio)
-#endif
-#if defined(CONFIG_VIOTAPE)
- || (subtype == viomajorsubtype_tape)
-#endif
- )
- {
- viopath_statuslock(remoteLp);
- switch (subtype) {
-#if defined(CONFIG_VIODASD)
- case viomajorsubtype_blockio:
- viopathStatus[remoteLp].xBlockUsers++;
- break;
-#endif
-#if defined(CONFIG_VIOCONS)
- case viomajorsubtype_chario:
- viopathStatus[remoteLp].xCharUsers++;
- break;
-#endif
-#if defined(CONFIG_VIOCD)
- case viomajorsubtype_cdio:
- viopathStatus[remoteLp].xCDUsers++;
- break;
-#endif
-#if defined(CONFIG_VIOTAPE)
- case viomajorsubtype_tape:
- viopathStatus[remoteLp].xTapeUsers++;
- break;
-#endif
- default:
- }
- if (!viopathStatus[remoteLp].isOpen)
- {
- HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo);
-
- viopathStatus[remoteLp].mSourceInst = HvCallEvent_getSourceLpInstanceId(remoteLp, HvLpEvent_Type_VirtualIo);
- viopathStatus[remoteLp].mTargetInst = HvCallEvent_getTargetLpInstanceId(remoteLp, HvLpEvent_Type_VirtualIo);
-
- printk("viopath: open, setting sinst %d, tinst %d\n",
- viopathStatus[remoteLp].mSourceInst,
- viopathStatus[remoteLp].mTargetInst);
-
- doneAllocParms.sem = &Semaphore;
-
- mf_allocateLpEvents(remoteLp,
- HvLpEvent_Type_VirtualIo,
- 250, /* TODO: Put a sizeof VIOLpEvent in here! */
- 25, /* TODO: Work out the real number */
- &viopath_donealloc,
- &doneAllocParms);
-
- down(&Semaphore);
-
- viopathStatus[remoteLp].numberAllocated = doneAllocParms.number;
-
- HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo, &vio_handleEvent);
-
- viopathStatus[remoteLp].isOpen = 1;
-
- hvrc = HvCallEvent_signalLpEventFast(remoteLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_monitor,
- HvLpEvent_AckInd_DoAck,
- HvLpEvent_AckType_DeferredAck,
- viopathStatus[remoteLp].mSourceInst,
- viopathStatus[remoteLp].mTargetInst,
- 0, 0, 0, 0, 0, 0);
-
- if (hvrc == HvLpEvent_Rc_Good)
- {
- viopathStatus[remoteLp].isActive = 1;
- }
- else
- {
- viopathStatus[remoteLp].isActive = 0;
- }
- }
- viopath_statusunlock(remoteLp);
-
- return 0;
- }
- else /* invalid subtype */
- {
- printk("viopath: invalid path subtype %d\n",subtype);
- return -EINVAL;
- }
-}
-
-int viopath_close(HvLpIndex remoteLp, int subtype)
-{
- printk("viopath: close(%d,%4.4x)\n",remoteLp,subtype);
-
- if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
- return -EINVAL;
-
- if ( (0)
-#if defined(CONFIG_VIODASD)
- || (subtype == viomajorsubtype_blockio)
-#endif
-#if defined(CONFIG_VIOCONS)
- || (subtype == viomajorsubtype_chario)
-#endif
-#if defined(CONFIG_VIOCD)
- || (subtype == viomajorsubtype_cdio)
-#endif
-#if defined(CONFIG_VIOTAPE)
- || (subtype == viomajorsubtype_tape)
-#endif
- )
- {
- viopath_statuslock(remoteLp);
- switch (subtype) {
-#if defined(CONFIG_VIODASD)
- case viomajorsubtype_blockio:
- viopathStatus[remoteLp].xBlockUsers--;
- break;
-#endif
-#if defined(CONFIG_VIOCONS)
- case viomajorsubtype_chario:
- viopathStatus[remoteLp].xCharUsers--;
- break;
-#endif
-#if defined(CONFIG_VIOCD)
- case viomajorsubtype_cdio:
- viopathStatus[remoteLp].xCDUsers--;
- break;
-#endif
-#if defined(CONFIG_VIOTAPE)
- case viomajorsubtype_tape:
- viopathStatus[remoteLp].xTapeUsers--;
- break;
-#endif
- default:
- }
-
- if ((viopathStatus[remoteLp].isOpen)
-#if defined(CONFIG_VIODASD)
- && (viopathStatus[remoteLp].xBlockUsers == 0)
-#endif
-#if defined(CONFIG_VIOCONS)
- && (viopathStatus[remoteLp].xCharUsers == 0)
-#endif
-#if defined(CONFIG_VIOCD)
- && (viopathStatus[remoteLp].xCDUsers == 0)
-#endif
-#if defined(CONFIG_VIOTAPE)
- && (viopathStatus[remoteLp].xTapeUsers == 0)
-#endif
- )
- {
- printk("viopath: closing event path\n");
- HvCallEvent_closeLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo);
- viopathStatus[remoteLp].isOpen = 0;
- viopathStatus[remoteLp].isActive = 0;
- }
- viopath_statusunlock(remoteLp);
-
- return 0;
- }
- else /* invalid subtype */
- {
- printk("viopath: invalid path subtype %d\n",subtype);
- return -EINVAL;
- }
-}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/kernel/xics.c linuxppc64_2_4/arch/ppc64/kernel/xics.c
--- linux-2.4.9-ac10/arch/ppc64/kernel/xics.c Thu Sep 6 14:05:11 2001
+++ linuxppc64_2_4/arch/ppc64/kernel/xics.c Wed Sep 5 13:56:40 2001
@@ -1,4 +1,4 @@
-/*
+/*
* arch/ppc/kernel/xics.c
*
* Copyright 2000 IBM Corporation.
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include "i8259.h"
#include "xics.h"
#include
@@ -50,6 +51,7 @@
#define XICS_IPI 2
#define XICS_IRQ_OFFSET 0x10
+#define XICS_PCI_IRQ_START 0x10
#define XICS_IRQ_SPURIOUS 0
@@ -77,19 +79,54 @@
struct xics_info xics_info;
-#define xirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.word)
-#define cppr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.bytes[0])
-#define poll_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr_poll.word)
-#define qirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->qirr.bytes[0])
-
unsigned long long intr_base = 0;
unsigned int xics_irq_8259_cascade = 0;
+unsigned int default_server = 0;
struct xics_interrupt_node {
unsigned long long addr;
unsigned long long size;
} inodes[NR_CPUS*2];
+typedef struct {
+ int (*xirr_info_get)(int cpu);
+ void (*xirr_info_set)(int cpu, int val);
+ void (*cppr_info)(int cpu, u8 val);
+ void (*qirr_info)(int cpu, u8 val);
+} xics_ops;
+
+
+static int pSeries_xirr_info_get(int n_cpu)
+{
+ return (xics_info.per_cpu[n_cpu]->xirr.word);
+}
+
+static void pSeries_xirr_info_set(int n_cpu, int value)
+{
+ xics_info.per_cpu[n_cpu]->xirr.word = value;
+}
+
+static void pSeries_cppr_info(int n_cpu, u8 value)
+{
+ xics_info.per_cpu[n_cpu]->xirr.bytes[0] = value;
+}
+
+static void pSeries_qirr_info(int n_cpu , u8 value)
+{
+ xics_info.per_cpu[n_cpu]->qirr.bytes[0] = value;
+}
+
+static xics_ops pSeries_ops = {
+ pSeries_xirr_info_get,
+ pSeries_xirr_info_set,
+ pSeries_cppr_info,
+ pSeries_qirr_info
+};
+
+static xics_ops *ops = &pSeries_ops;
+
+
+
void
xics_enable_irq(
u_int irq
@@ -102,9 +139,9 @@
if (irq == XICS_IPI)
return;
call_status = call_rtas("ibm,set-xive", 3, 1, (unsigned long*)&status,
- irq, cpu_hw_index[0], DEFAULT_PRIORITY);
+ irq, default_server, DEFAULT_PRIORITY);
if( call_status != 0 ) {
- printk("xics_enable_irq: irq=%x: call_rtas failed; retn=%x, status=%x\n",
+ printk("xics_enable_irq: irq=%x: call_rtas failed; retn=%lx, status=%lx\n",
irq, call_status, status);
return;
}
@@ -122,9 +159,8 @@
call_status = call_rtas("ibm,int-off", 1, 1, (unsigned long*)&status,
irq);
if( call_status != 0 ) {
- printk("xics_disable_irq: irq=%x: call_rtas failed, retn=%x\n",
+ printk("xics_disable_irq: irq=%x: call_rtas failed, retn=%ld\n",
irq, call_status);
- return;
}
}
@@ -135,9 +171,9 @@
{
int cpu = smp_processor_id();
- cppr_info(cpu) = 0; /* actually the value overwritten by ack */
+ ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */
iosync();
- xirr_info(cpu) = (0xff<<24) | (irq-XICS_IRQ_OFFSET);
+ ops->xirr_info_set(cpu, ((0xff<<24) | (irq-XICS_IRQ_OFFSET)));
iosync();
}
@@ -151,11 +187,11 @@
if( irq < XICS_IRQ_OFFSET ) {
i8259_pic.ack(irq);
iosync();
- xirr_info(cpu) = (0xff<<24) | xics_irq_8259_cascade;
+ ops->xirr_info_set(cpu, ((0xff<<24) | xics_irq_8259_cascade));
iosync();
}
else {
- cppr_info(cpu) = 0xff;
+ ops->cppr_info(cpu, 0xff);
iosync();
}
}
@@ -166,8 +202,8 @@
u_int cpu = smp_processor_id();
u_int vec;
int irq;
-
- vec = xirr_info(cpu);
+
+ vec = ops->xirr_info_get(cpu);
/* (vec >> 24) == old priority */
vec &= 0x00ffffff;
/* for sanity, this had better be < NR_IRQS - 16 */
@@ -176,10 +212,12 @@
if(irq == -1) {
/* Spurious cascaded interrupt. Still must ack xics */
xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade);
+ irq = -1;
}
- } else if( vec == XICS_IRQ_SPURIOUS )
+ } else if( vec == XICS_IRQ_SPURIOUS ) {
irq = -1;
- else
+ printk("spurious PPC interrupt!\n");
+ } else
irq = vec + XICS_IRQ_OFFSET;
return irq;
}
@@ -198,9 +236,8 @@
{
extern volatile unsigned long xics_ipi_message[];
int cpu = smp_processor_id();
-
- qirr_info(cpu) = 0xff;
+ ops->qirr_info(cpu, 0xff);
while (xics_ipi_message[cpu]) {
if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu])) {
mb();
@@ -211,19 +248,18 @@
smp_message_recv(PPC_MSG_RESCHEDULE, regs);
}
}
-
}
void xics_cause_IPI(int cpu)
{
- qirr_info(cpu) = 0;
+ ops->qirr_info(cpu,0) ;
}
void xics_setup_cpu(void)
{
int cpu = smp_processor_id();
- cppr_info(cpu) = 0xff;
+ ops->cppr_info(cpu, 0xff);
iosync();
}
#endif /* CONFIG_SMP */
@@ -274,6 +310,9 @@
np = np->next;
if ((indx < NR_CPUS) && np) goto nextnode;
+ /* For now all interrupts go through this cpu (not necessarily cpu #0)... */
+ default_server = hard_smp_processor_id();
+
/*
* XXX Assume for now that nodes are in order
* We could (and should) get the "interrupt-server-ranges" property
@@ -303,15 +342,17 @@
xics_irq_8259_cascade = *ireg;
+ if (_machine == _MACH_pSeries) {
#ifdef CONFIG_SMP
- for (i = 0; i < naca->processorCount; ++i) {
- xics_info.per_cpu[i] =
- ioremap((ulong)inodes[cpu_hw_index[i]].addr,
- (ulong)inodes[cpu_hw_index[i]].size);
- }
+ for (i = 0; i < naca->processorCount; ++i) {
+ xics_info.per_cpu[i] =
+ ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr,
+ (ulong)inodes[get_hard_smp_processor_id(i)].size);
+ }
#else
- xics_info.per_cpu[0] = ioremap((ulong)intr_base, intr_size);
+ xics_info.per_cpu[0] = ioremap((ulong)intr_base, intr_size);
#endif /* CONFIG_SMP */
+ }
xics_8259_pic.enable = i8259_pic.enable;
xics_8259_pic.disable = i8259_pic.disable;
@@ -320,7 +361,7 @@
for (; i < NR_IRQS; ++i)
irq_desc[i].handler = &xics_pic;
- cppr_info(0) = 0xff;
+ ops->cppr_info(0, 0xff);
iosync();
if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action,
0, "8259 cascade", 0))
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/mm/init.c linuxppc64_2_4/arch/ppc64/mm/init.c
--- linux-2.4.9-ac10/arch/ppc64/mm/init.c Thu Sep 6 14:05:11 2001
+++ linuxppc64_2_4/arch/ppc64/mm/init.c Fri Sep 14 22:12:42 2001
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#ifdef CONFIG_BLK_DEV_INITRD
#include /* for initrd_* */
#endif
@@ -94,9 +95,7 @@
extern unsigned long *find_end_of_memory(void);
extern pgd_t ioremap_dir[];
-extern pgd_t bolted_dir[];
pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir;
-pgd_t * bolted_pgd = (pgd_t *)&bolted_dir;
static void map_io_page(unsigned long va, unsigned long pa, int flags);
extern void die_if_kernel(char *,struct pt_regs *,long);
@@ -220,7 +219,12 @@
void *
ioremap(unsigned long addr, unsigned long size)
{
+#ifdef CONFIG_PPC_ISERIES
+ /* iSeries I/O Remap is a noop */
+ return (void*)addr;
+#else
return __ioremap(addr, size, _PAGE_NO_CACHE);
+#endif
}
extern struct vm_struct * get_im_area( unsigned long size );
@@ -291,9 +295,15 @@
return (void *) (ea + (addr & ~PAGE_MASK));
}
-void iounmap(void *addr)
+void iounmap(void *addr)
{
+#ifdef CONFIG_PPC_ISERIES
+ /* iSeries I/O Remap is a noop */
+ return;
+#else
/* DRENG / PPPBBB todo */
+ return;
+#endif
}
unsigned long iopa(unsigned long addr)
@@ -366,6 +376,9 @@
local_flush_tlb_range( mm, mp->vm_start, mp->vm_end );
}
else /* MIKEC: It is not clear why this is needed */
+ /* paulus: it is needed to clear out stale HPTEs
+ * when an address space (represented by an mm_struct)
+ * is being destroyed. */
local_flush_tlb_range( mm, USER_START, USER_END );
}
@@ -389,9 +402,6 @@
case IO_REGION_ID:
pgd = pgd_offset_i( vmaddr );
break;
- case BOLTED_REGION_ID:
- pgd = pgd_offset_b( vmaddr );
- break;
case USER_REGION_ID:
pgd = pgd_offset( vma->vm_mm, vmaddr );
context = vma->vm_mm->context;
@@ -440,9 +450,6 @@
case IO_REGION_ID:
pgd = pgd_offset_i( start );
break;
- case BOLTED_REGION_ID:
- pgd = pgd_offset_b( start );
- break;
case USER_REGION_ID:
pgd = pgd_offset( mm, start );
context = mm->context;
@@ -682,3 +689,46 @@
}
+
+/*
+ * This is called when a page has been modified by the kernel.
+ * It just marks the page as not i-cache clean. We do the i-cache
+ * flush later when the page is given to a user process, if necessary.
+ */
+void flush_dcache_page(struct page *page)
+{
+ clear_bit(PG_arch_1, &page->flags);
+}
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ * On machines which use an MMU hash table we avoid changing the
+ * _PAGE_HASHPTE bit.
+ * If the new PTE has _PAGE_EXEC set, meaning that the user wants
+ * to be able to execute out of the page, we check if the page is
+ * i-cache dirty and flush it if so, and mark it clean.
+ */
+void set_pte(pte_t *ptep, pte_t pte)
+{
+ pte_update(ptep, ~_PAGE_HPTEFLAGS, pte_val(pte) & ~_PAGE_HPTEFLAGS);
+ if (mem_init_done && (pte_val(pte) & _PAGE_EXEC)
+ && pte_pagenr(pte) < max_mapnr) {
+ struct page *page = pte_page(pte);
+ if (!test_bit(PG_arch_1, &page->flags)) {
+ __flush_dcache_icache((unsigned long)page_address(page));
+ set_bit(PG_arch_1, &page->flags);
+ }
+ }
+}
+
+void clear_user_page(struct page *page, unsigned long vaddr)
+{
+ clear_mem_page(page);
+ clear_bit(PG_arch_1, &page->flags);
+}
+
+void copy_user_page(struct page *to, struct page *from, unsigned long vaddr)
+{
+ copy_mem_page(to, from);
+ clear_bit(PG_arch_1, &to->flags);
+}
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/vmlinux.lds linuxppc64_2_4/arch/ppc64/vmlinux.lds
--- linux-2.4.9-ac10/arch/ppc64/vmlinux.lds Thu Sep 6 14:05:11 2001
+++ linuxppc64_2_4/arch/ppc64/vmlinux.lds Tue Sep 11 08:55:40 2001
@@ -104,7 +104,6 @@
. = ALIGN(4096);
__init_end = .;
- . = ALIGN(4096);
__chrp_begin = .;
.text.chrp : { *(.text.chrp) }
.data.chrp : { *(.data.chrp) }
@@ -118,8 +117,6 @@
. = ALIGN(4096);
__openfirmware_end = .;
-
- . = ALIGN(4096);
__toc_start = .;
.toc :
{
@@ -128,7 +125,6 @@
. = ALIGN(4096);
__toc_end = .;
- . = ALIGN(4096);
__bss_start = .;
.bss :
{
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/xmon/privinst.h linuxppc64_2_4/arch/ppc64/xmon/privinst.h
--- linux-2.4.9-ac10/arch/ppc64/xmon/privinst.h Thu Sep 6 14:05:11 2001
+++ linuxppc64_2_4/arch/ppc64/xmon/privinst.h Fri Sep 14 20:00:19 2001
@@ -44,7 +44,6 @@
GSETSPR(275, sprg3)
GSETSPR(282, ear)
GSETSPR(287, pvr)
-#ifndef CONFIG_8xx
GSETSPR(528, bat0u)
GSETSPR(529, bat0l)
GSETSPR(530, bat1u)
@@ -58,13 +57,6 @@
GSETSPR(1010, iabr)
GSETSPR(1013, dabr)
GSETSPR(1023, pir)
-#else
-GSETSPR(144, cmpa)
-GSETSPR(145, cmpb)
-GSETSPR(146, cmpc)
-GSETSPR(147, cmpd)
-GSETSPR(158, ictrl)
-#endif
static inline int get_sr(int n)
{
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/xmon/start.c linuxppc64_2_4/arch/ppc64/xmon/start.c
--- linux-2.4.9-ac10/arch/ppc64/xmon/start.c Thu Sep 6 14:05:11 2001
+++ linuxppc64_2_4/arch/ppc64/xmon/start.c Wed Sep 5 13:56:41 2001
@@ -18,6 +18,12 @@
#include
#include
+/* Transition to udbg isn't quite done yet...but very close. */
+#define USE_UDBG 1
+#ifdef USE_UDBG
+#include
+#endif
+
static volatile unsigned char *sccc, *sccd;
unsigned long TXRDY, RXRDY;
extern void xmon_printf(const char *fmt, ...);
@@ -38,11 +44,12 @@
return ret;
}
+#ifndef USE_UDBG
void buf_access(void)
{
- if ( _machine == _MACH_chrp )
- sccd[3] &= ~0x80; /* reset DLAB */
+ sccd[3] &= ~0x80; /* reset DLAB */
}
+#endif
extern int adb_init(void);
@@ -60,13 +67,15 @@
void
xmon_map_scc(void)
{
+ /* This maybe isn't the best place to register sysrq 'x' */
+ __sysrq_put_key_op('x', &sysrq_xmon_op);
+#ifndef USE_UDBG
/* should already be mapped by the kernel boot */
sccd = (volatile unsigned char *) (((unsigned long)comport1));
sccc = (volatile unsigned char *) (((unsigned long)comport1)+5);
TXRDY = 0x20;
RXRDY = 1;
- /* This maybe isn't the best place to register sysrq 'x' */
- __sysrq_put_key_op('x', &sysrq_xmon_op);
+#endif
}
static int scc_initialized = 0;
@@ -77,6 +86,9 @@
int
xmon_write(void *handle, void *ptr, int nb)
{
+#ifdef USE_UDBG
+ return udbg_write(ptr, nb);
+#else
char *p = ptr;
int i, c, ct;
@@ -100,6 +112,7 @@
*sccd = c;
}
return i;
+#endif
}
int xmon_wants_key;
@@ -108,6 +121,9 @@
int
xmon_read(void *handle, void *ptr, int nb)
{
+#ifdef USE_UDBG
+ return udbg_read(ptr, nb);
+#else
char *p = ptr;
int i, c;
@@ -123,34 +139,34 @@
*p++ = c;
}
return i;
+#endif
}
int
xmon_read_poll(void)
{
+#ifdef USE_UDBG
+ return -1; /* ToDo: need a udbg_poll_getc() */
+#else
if ((*sccc & RXRDY) == 0) {
-#ifdef CONFIG_ADB_PMU
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll();
-#endif /* CONFIG_ADB_PMU */
return -1;
}
buf_access();
return *sccd;
+#endif
}
void
xmon_init_scc()
{
- if ( _machine == _MACH_chrp )
- {
- sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
- sccd[0] = 12; eieio(); /* DLL = 9600 baud */
- sccd[1] = 0; eieio();
- sccd[2] = 0; eieio(); /* FCR = 0 */
- sccd[3] = 3; eieio(); /* LCR = 8N1 */
- sccd[1] = 0; eieio(); /* IER = 0 */
- }
+#ifndef USE_UDBG
+ sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
+ sccd[0] = 12; eieio(); /* DLL = 9600 baud */
+ sccd[1] = 0; eieio();
+ sccd[2] = 0; eieio(); /* FCR = 0 */
+ sccd[3] = 3; eieio(); /* LCR = 8N1 */
+ sccd[1] = 0; eieio(); /* IER = 0 */
+#endif
scc_initialized = 1;
if (via_modem) {
diff -uNr --exclude=CVS linux-2.4.9-ac10/arch/ppc64/xmon/xmon.c linuxppc64_2_4/arch/ppc64/xmon/xmon.c
--- linux-2.4.9-ac10/arch/ppc64/xmon/xmon.c Thu Sep 6 14:05:11 2001
+++ linuxppc64_2_4/arch/ppc64/xmon/xmon.c Fri Sep 14 21:59:08 2001
@@ -496,6 +496,8 @@
int i;
struct bpt *bp;
+ if (_machine != _MACH_pSeries)
+ return;
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
if (!bp->enabled)
@@ -525,6 +527,8 @@
struct bpt *bp;
unsigned instr;
+ if (_machine != _MACH_pSeries)
+ return;
if (!__is_processor(PV_POWER4)) {
set_dabr(0);
set_iabr(0);
@@ -1156,7 +1160,6 @@
// Dump out relevant Paca data areas.
printf("Paca: \n");
ptrPaca = (struct Paca*)get_sprg3();
- printf(" Saved Gpr21=%.16lx Saved Gpr22 =%.16lx \n", ptrPaca->xR21, ptrPaca->xR22);
printf(" Local Processor Control Area (LpPaca): \n");
ptrLpPaca = ptrPaca->xLpPacaPtr;
@@ -2169,8 +2172,7 @@
termch = c;
scanhex((void *)&ea);
- if ( (( ea >= KRANGE_START ) && ( ea <= (KRANGE_START + (1UL<<60) ))) ||
- (( ea >= BTMALLOC_START) && ( ea <= BTMALLOC_END)) ) {
+ if ((ea >= KRANGE_START) && (ea <= (KRANGE_START + (1UL<<60)))) {
ptep = 0;
vsid = get_kernel_vsid(ea);
va = ( vsid << 28 ) | ( ea & 0x0fffffff );
@@ -2931,8 +2933,8 @@
((p->thread.regs)->ctr), ((p->thread.regs)->link));
printf(" xer : 0x%16.16lx ccr : 0x%16.16lx\n",
((p->thread.regs)->xer), ((p->thread.regs)->ccr));
- printf(" mq : 0x%16.16lx trap : 0x%16.16lx\n",
- ((p->thread.regs)->mq), ((p->thread.regs)->trap));
+ printf(" trap : 0x%16.16lx\n",
+ ((p->thread.regs)->trap));
printf(" dar : 0x%16.16lx dsis : 0x%16.16lx\n",
((p->thread.regs)->dar), ((p->thread.regs)->dsisr));
printf(" rslt : 0x%16.16lx org3 : 0x%16.16lx\n",
diff -uNr --exclude=CVS linux-2.4.9-ac10/drivers/block/Config.in linuxppc64_2_4/drivers/block/Config.in
--- linux-2.4.9-ac10/drivers/block/Config.in Thu Sep 6 14:03:35 2001
+++ linuxppc64_2_4/drivers/block/Config.in Fri Aug 17 13:03:16 2001
@@ -28,6 +28,12 @@
tristate ' Atari SLM laser printer support' CONFIG_ATARI_SLM
fi
fi
+if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
+ dep_tristate 'iSeries Virtual I/O disk support' CONFIG_VIODASD $CONFIG_PPC_ISERIES
+ if [ "$CONFIG_VIODASD" = "y" -o "$CONFIG_VIODASD" = "m" ]; then
+ bool 'iSeries Virtual disk IDE emulation' CONFIG_VIODASD_IDE
+ fi
+fi
dep_tristate 'XT hard disk support' CONFIG_BLK_DEV_XD $CONFIG_ISA
dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARPORT
if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
diff -uNr --exclude=CVS linux-2.4.9-ac10/drivers/block/Makefile linuxppc64_2_4/drivers/block/Makefile
--- linux-2.4.9-ac10/drivers/block/Makefile Thu Sep 6 14:11:11 2001
+++ linuxppc64_2_4/drivers/block/Makefile Mon Sep 10 10:54:08 2001
@@ -20,6 +20,7 @@
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
+obj-$(CONFIG_VIODASD) += viodasd.o
obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o
obj-$(CONFIG_ATARI_ACSI) += acsi.o
obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
diff -uNr --exclude=CVS linux-2.4.9-ac10/drivers/block/genhd.c linuxppc64_2_4/drivers/block/genhd.c
--- linux-2.4.9-ac10/drivers/block/genhd.c Thu Sep 6 14:11:16 2001
+++ linuxppc64_2_4/drivers/block/genhd.c Mon Sep 10 14:04:09 2001
@@ -194,6 +194,9 @@
#ifdef CONFIG_VT
console_map_init();
#endif
+#ifdef CONFIG_VIODASD
+ viodasd_init();
+#endif
return 0;
}
diff -uNr --exclude=CVS linux-2.4.9-ac10/drivers/block/ll_rw_blk.c linuxppc64_2_4/drivers/block/ll_rw_blk.c
--- linux-2.4.9-ac10/drivers/block/ll_rw_blk.c Thu Sep 6 14:03:35 2001
+++ linuxppc64_2_4/drivers/block/ll_rw_blk.c Fri Aug 10 13:08:53 2001
@@ -1229,6 +1229,9 @@
#ifdef CONFIG_BLK_DEV_XD
xd_init();
#endif
+#ifdef CONFIG_VIOCD
+ viocd_init();
+#endif
#ifdef CONFIG_BLK_DEV_MFM
mfm_init();
#endif
diff -uNr --exclude=CVS linux-2.4.9-ac10/drivers/block/viodasd.c linuxppc64_2_4/drivers/block/viodasd.c
--- linux-2.4.9-ac10/drivers/block/viodasd.c Wed Dec 31 18:00:00 1969
+++ linuxppc64_2_4/drivers/block/viodasd.c Fri Sep 7 13:45:16 2001
@@ -0,0 +1,1414 @@
+/* -*- linux-c -*-
+ * viodasd.c
+ * Authors: Dave Boutcher
+ * Ryan Arnold
+ * Colin Devilbiss
+ *
+ * (C) Copyright 2000 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ***************************************************************************
+ * This routine provides access to disk space (termed "DASD" in historical
+ * IBM terms) owned and managed by an OS/400 partition running on the
+ * same box as this Linux partition.
+ *
+ * All disk operations are performed by sending messages back and forth to
+ * the OS/400 partition.
+ *
+ * This device driver can either use it's own major number, or it can
+ * pretend to be an IDE drive (Major #3). Currently it doesn't
+ * emulate all the other IDE majors. This is controlled with a
+ * CONFIG option. You can either call this an elegant solution to the
+ * fact that a lot of software doesn't recognize a new disk major number...
+ * or you can call this a really ugly hack. Your choice.
+ */
+
+#include
+#include
+
+/* Decide if we are using our own major or pretending to be an IDE drive
+ *
+ * If we are using our own majors, we only support 3 partitions per physical
+ * disk....so with minor numbers 0-255 we get a maximum of 64 disks. If we
+ * are emulating IDE, we get 16 partitions per disk, with a maximum of 16
+ * disks
+ */
+#ifdef CONFIG_VIODASD_IDE
+#define MAJOR_NR IDE0_MAJOR
+#define PARTITION_SHIFT 6
+#define do_viodasd_request do_hd_request
+static int numdsk = 16;
+static int viodasd_max_disk = 16;
+#define VIOD_DEVICE_NAME "hd"
+#define VIOD_GENHD_NAME "hd"
+#else
+#define MAJOR_NR VIODASD_MAJOR
+#define PARTITION_SHIFT 3
+static int numdsk = 32;
+static int viodasd_max_disk = 32;
+#define VIOD_DEVICE_NAME "viod"
+#ifdef CONFIG_DEVFS_FS
+#define VIOD_GENHD_NAME "viod"
+#else
+#define VIOD_GENHD_NAME "iSeries/vd"
+#endif /* CONFIG_DEVFS */
+#endif /* CONFIG_VIODASD_IDE */
+
+#define VIODASD_VERS "1.02"
+#define LOCAL_END_REQUEST
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include