diff -u --recursive --new-file v2.4.9/linux/Documentation/00-INDEX linux/Documentation/00-INDEX --- v2.4.9/linux/Documentation/00-INDEX Thu Feb 8 16:32:44 2001 +++ linux/Documentation/00-INDEX Mon Aug 27 07:44:15 2001 @@ -5,6 +5,11 @@ Please try and keep the descriptions small enough to fit on one line. Thanks -- Paul G. +Following translations are available on the WWW: + + - Japanese, maintained by the JF Project (JF@linux.or.jp), at + http://www.linux.or.jp/JF/ + 00-INDEX - this file. BUG-HUNTING diff -u --recursive --new-file v2.4.9/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.9/linux/Documentation/Configure.help Mon Aug 27 12:41:37 2001 +++ linux/Documentation/Configure.help Tue Aug 28 11:21:02 2001 @@ -1746,6 +1746,36 @@ similar) CPU, R4xx0 might be a safe bet. If the resulting Kernel does not work try to recompile with R3000. +CPU type +CONFIG_CPU_VR41XX + The options selects support for the NEC VR41xx series of processors. + Only choose this option if you have one of these processors as a + kernel built with this option will not run on any other type of + processor or vice versa. + +CPU feature configuration +CONFIG_CPU_ADVANCED + Saying yes here allows you to select support for various features your + CPU may or may not have. Most people should say N here. + +ll and sc instructions +CONFIG_CPU_HAS_LLSC + Say Y here if your CPU has the ll and sc instructions. Say Y here for + better performance, N if you don't know. You must say Y here for + multiprocessor machines. + +lld and scd instructions +CONFIG_CPU_HAS_LLDSCD + Say Y here if your CPU has the lld and scd instructions, the 64-bit + equivalents of ll and sc. Say Y here for better performance, N if + you don't know. You must say Y here for multiprocessor machines. + +Support for writebuffer flushing +CONFIG_CPU_HAS_WB + Say N here for slightly better performance. You must say Y here for + machines which require flushing of write buffers in software. Saying + Y is the safe option; N may result in kernel malfunction and crashes. + Support for large 64-bit configurations CONFIG_MIPS_INSANE_LARGE MIPS R10000 does support a 44 bit / 16TB address space as opposed to @@ -11478,6 +11508,45 @@ The module will be called pegasus.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +CONFIG_USB_KAWETH + Say Y here if you want to use one of the following 10Mbps only + USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: + 3Com 3C19250 + ADS USB-10BT + ATEN USB Ethernet + ASANTE USB To Ethernet Adapter + AOX Endpoints USB Ethernet + Correga K.K. + D-Link DSB-650C and DU-E10 + Entrega / Portgear E45 + I-O DATA USB-ET/T + Jaton USB Ethernet Device Adapter + Kingston Technology USB Ethernet Adapter + Linksys USB10T + Mobility USB-Ethernet Adapter + NetGear EA-101 + Peracom Enet and Enet2 + Portsmith Express Ethernet Adapter + Shark Pocket Adapter + SMC 2202USB + Sony Vaio port extender + + This driver is likely to work with most 10Mbps only USB Ethernet + adapters, including some "no brand" devices. It does NOT work on + SmartBridges smartNIC or on Belkin F5U111 devices - you should use + the CATC NetMate driver for those. If you are not sure which one + you need, select both, and the correct one should be selected for + you. + + This driver makes the adapter appear as a normal Ethernet interface, + typically on eth0, if it is the only ethernet device, or perhaps on + eth1, if you have a PCI or ISA ethernet card installed. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called kaweth.o. If you want to compile it as a + module, say M here and read . + USB CATC NetMate-based Ethernet device support CONFIG_USB_CATC Say Y if you want to use one of the following 10Mbps USB Ethernet @@ -11604,6 +11673,23 @@ The module will be called dabusb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +Host-to-Host USB networking +CONFIG_USB_USBNET + This driver supports network links over USB with USB "Network" + or "data transfer" cables, often used to network laptops to PCs. + Such cables have chips from suppliers such as NetChip and Prolific. + Intelligent USB devices could also use this approach to provide + Internet access, using standard USB cabling. + + These links will have names like "usb0", "usb1", etc. They act + like two-node Ethernets, so you can use 802.1d Ethernet Bridging + (CONFIG_BRIDGE) to simplify your network routing. + + This code is also available as a kernel module (code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called usbnet.o. If you want to compile it as a + module, say M here and read . + PLUSB driver CONFIG_USB_PLUSB A driver for the Prolific PL-2302 USB-to-USB network device. This @@ -15754,6 +15840,14 @@ better 32 MB RAM to avoid excessive linking time. This is only useful for kernel hackers. If unsure, say N. +Run uncached +CONFIG_MIPS_UNCACHED + If you say Y here there kernel will disable all CPU caches. This will + reduce the system's performance dramatically but can help finding + otherwise hard to track bugs. It can also useful if you're doing + hardware debugging with a logic analyzer and need to see all traffic + on the bus. + Magic System Request Key support CONFIG_MAGIC_SYSRQ If you say Y here, you will have some control over the system even @@ -16983,11 +17077,75 @@ CONFIG_ALL_PPC Linux currently supports several different kinds of PowerPC-based machines: Apple Power Macintoshes and clones (such as the Motorola - Starmax series), PReP (PowerPC Reference Platform) machines such as - the Motorola PowerStack, CHRP (Common Hardware Reference Platform), - the embedded MBX boards from Motorola and many others. Currently, - the default option is to build a kernel which works on the first - three. Support for other machines is currently incomplete. + Starmax series), PReP (PowerPC Reference Platform) machines (such + as the Motorola PowerStacks, Motorola cPCI/VME embedded systems, + and some IBM RS/6000 systems), CHRP (Common Hardware Reference + Platform), and several embedded PowerPC systems containing 4xx, 6xx, + 7xx, 8xx, 74xx, and 82xx processors. Currently, the default option + is to build a kernel which works on the first three. + +AltiVec Kernel Support +CONFIG_ALTIVEC + This option enables kernel support for the Altivec extensions to the + PowerPC processor. The kernel currently supports saving and restoring + altivec registers, and turning on the 'altivec enable' bit so user + processes can execute altivec instructions. + + This option is only usefully if you have a processor that supports + altivec (G4, otherwise known as 74xx series), but does not have + any affect on a non-altivec cpu (it does, however add code to the + kernel). + + If in doubt, say Y here. + +Thermal Management Support +CONFIG_TAU + G3 and G4 processors have an on-chip temperature sensor called the + 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die + temperature within 2-4 degrees celcius. This option shows the current + on-die temperature in /proc/cpuinfo if the cpu supports it. + + Unfortunately, on some chip revisions, this sensor is very inaccurate + and in some cases, does not work at all, so don't assume the cpu + temp is actually what /proc/cpuinfo says it is. + +Interrupt driven TAU driver +CONFIG_TAU_INT + The TAU supports an interrupt driven mode which causes an interrupt + whenever the temperature goes out of range. This is the fastest way + to get notified the temp has exceeded a range. With this option off, + a timer is used to re-check the temperature periodically. + + However, on some cpus it appears that the TAU interrupt hardware + is buggy and can cause a situation which would lead unexplained hard + lockups. + + Unless you are extending the TAU driver, or enjoy kernel/hardware + debugging, leave this option off. + +Average high and low temp +CONFIG_TAU_AVERAGE + The TAU hardware can compare the temperature to an upper and lower bound. + The default behavior is to show both the upper and lower bound in + /proc/cpuinfo. If the range is large, the temperature is either changing + a lot, or the TAU hardware is broken (likely on some G4's). If the range + is small (around 4 degrees), the temperature is relatively stable. + +Support for CUDA based PowerMacs +CONFIG_ADB_CUDA + This provides support for CUDA based Power Macintosh systems. This + includes most OldWorld PowerMacs, the first generation iMacs, the + Blue&White G3 and the Yikes G4 (PCI Graphics). All later models + should use CONFIG_ADB_PMU instead. + + If unsure say Y. + +Support for PMU based PowerMacs +CONFIG_ADB_PMU + This provides support for PMU based Power Macintosh systems. This + includes all PowerBooks and all AGP-based machines. + + If unsure say Y. Power management support for PowerBooks CONFIG_PMAC_PBOOK @@ -17004,13 +17162,6 @@ You may also want to compile the dma sound driver as a module and have it autoloaded. The act of removing the module shuts down the sound hardware for more power savings. - -Mac-on-Linux support -CONFIG_MOL - This option enables low-level support for Mac-on-Linux. - MOL lets you run MacOS and Linux simultaneously. Please - visit for more information. - If unsure, say Y. ADB raw keycode support CONFIG_MAC_ADBKEYCODES diff -u --recursive --new-file v2.4.9/linux/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt --- v2.4.9/linux/Documentation/filesystems/ntfs.txt Mon Aug 27 12:41:37 2001 +++ linux/Documentation/filesystems/ntfs.txt Tue Aug 28 06:57:18 2001 @@ -64,6 +64,26 @@ Be careful not to write anything to them or you could crash the kernel and/or corrupt your file system! +mft_zone_multiplier= Set the MFT zone multiplier for the volume (this + setting is not persistent across mounts and can be + changed from mount to mount but cannot be changed on + remount). Values of 1 to 4 are allowed, 1 being the + default. The MFT zone multiplier determines how much + space is reserved for the MFT on the volume. If all + other space is used up, then the MFT zone will be + shrunk dynamically, so this has no impact on the + amount of free space. However, it can have an impact + on performance by affecting fragmentation of the MFT. + In general use the default. If you have a lot of small + files then use a higher value. The values have the + following meaning: + Value MFT zone size (% of volume size) + 1 12.5% + 2 25% + 3 37.5% + 4 50% + NOTE: This is currently ignored! Work in progress. + Known bugs and (mis-)features ============================= @@ -71,17 +91,45 @@ use it, get the Linux-NTFS tools and use the ntfsfix utility after dismounting a partition you wrote to. -- Use the show_sys_files mount option which should make things work generally - better. (It results in both the short and long file names being shown as well - as the sytem files.) - - Writing of extension records is not supported properly. +- $MFT extension is badly broken and really needs rewriting. + Please send bug reports/comments/feed back/abuse to the Linux-NTFS development list at sourceforge: linux-ntfs-dev@lists.sourceforge.net ChangeLog ========= + +NTFS 1.1.17: + + - Fixed system file handling. No longer need to use show_sys_files + option for driver to work fine. System files are now always treated + the same, but without the option, they are made invisible to + directory listings. As a result system files can once again be opened + even without the show_sys_files option. This is important for the + statfs system call to work properly, for example. + - Implemented MFT zone including mount parameter to tune it (just like + in Windows via the registry, only we make it per mount rather than + global for the whole driver, so we are better but we have no way of + storing the value as we don't have a registry so either specify on + each mount or put it in /etc/fstab). [Stage 1 of 3, mount parameter + handling.] + - Fixed fixup functions to handle corruption cases and to return error + codes to the caller. + - Made fixup functions apply hotfixes where sensible. [Stage 1 of 2+, + in memory only.] + - Fixed ommission of "NTFS: " string in ntfs_error() output. + - Fixed stupid if statement bug in unistr.c. Thanks to Yann E. Morin + for spotting it. + - Get rid of all uses of max and min macros. This actually allowed for + optimizing the code in several places so it was a Good Thing(TM). + - Make ntfs use generic_file_open to enforce the O_LARGEFILE flag. + - Detect encrypted files and refuse to access them (return EACCES + error code to user space). + - Fix handling of encrypted & compressed files so that an encrypted + file no longer is considered to be compressed (this was causing + kernel segmentation faults). NTFS 1.1.16: diff -u --recursive --new-file v2.4.9/linux/Documentation/mips/pci/pci.README linux/Documentation/mips/pci/pci.README --- v2.4.9/linux/Documentation/mips/pci/pci.README Wed Dec 31 16:00:00 1969 +++ linux/Documentation/mips/pci/pci.README Mon Aug 27 08:56:31 2001 @@ -0,0 +1,67 @@ + +Pete Popov, ppopov@pacbell.net +07/11/2001 + +This README briefly explains how to use the pci and pci_auto +code in arch/mips/kernel. The code was ported from PowerPC and +modified slightly. It has been tested pretty well on PPC on some +rather complex systems with multiple bridges and devices behind +each bridge. However, at the time this README was written, the +mips port was tested only on boards with a single pci bus and +no P2P bridges. It's very possible that on boards with P2P +bridges some modifications have to be made. The code will +evolve, no doubt, but currently every single mips board +is doing its own pcibios thing and it has become a big +mess. This generic pci code is meant to clean up the mips +pci mess and make it easier to add pci support to new boards. + +arch/mips/kernel/pci_auto.c has the pci bus enumeration code. +This code scans the pci bus(es) and assigns all of the resources. +Thus, you don't need the boot code to that, and many boot codes +don't do it correctly anyway. To enable the pci_auto code, add + +define_bool CONFIG_PCI_AUTO y + +inside the define for your board in arch/mips/config.in. +For example, the Galileo EV96100 board looks like this: + +if [ "$CONFIG_MIPS_EV96100" = "y" ]; then + define_bool CONFIG_PCI y + define_bool CONFIG_MIPS_GT96100 y + define_bool CONFIG_NEW_PCI y + define_bool CONFIG_PCI_AUTO y + define_bool CONFIG_SWAP_IO_SPACE y +fi + + +Next, if you want to use the arch/mips/kernel/pci code, which has the +pcibios_init() function, add + +define_bool CONFIG_NEW_PCI y + +inside the define for your board. Again, the EV96100 example above +show NEW_PCI turned on. + +Note that you can enable CONFIG_NEW_PCI code without enabling +CONFIG_PCI_AUTO. But you can't do the opposite because the pci_auto +routines are called from pcibios_init(), which is part of the +CONFIG_NEW_PCI code. + + +Now you need to add your files to hook in your pci configuration +cycles. Usually you'll need only a couple of files named something +like pci_fixups.c and pci_ops.c. You can copy the templates +provided and fill in the code. + +The file pci_ops.c should contain the pci configuration cycles routines. +It also has the mips_pci_channels[] array which contains the descriptors +of each pci controller. + +The file pci_fixups.c contains a few routines to do interrupt fixups, +resources fixups, and, if needed, pci bios fixups. + +Usually you'll put your pci_fixups.c file in your board specific directory, +since the functions in that file are board specific. The functions in +pci_ops.c, on the other hand, are usually pci controller specific so that +file could be shared among a few different boards using the same +pci controller. diff -u --recursive --new-file v2.4.9/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.9/linux/MAINTAINERS Mon Aug 27 12:41:37 2001 +++ linux/MAINTAINERS Mon Aug 27 08:56:31 2001 @@ -689,8 +689,8 @@ S: Orphan IEEE 1394 OHCI DRIVER -P: Sebastien Rougeaux -M: sebastien.rougeaux@anu.edu.au +P: Ben Collins +M: bcollins@debian.org L: linux1394-devel@lists.sourceforge.net S: Maintained @@ -902,9 +902,9 @@ MIPS P: Ralf Baechle -M: ralf@gnu.ai.mit.edu -W: http://lena.fnet.fr/ -L: linux-mips@fnet.fr +M: ralf@gnu.org +W: http://oss.sgi.com/mips/mips-howto.html +L: linux-mips@oss.sgi.com S: Maintained MISCELLANEOUS MCA-SUPPORT @@ -1452,6 +1452,13 @@ L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained + +USB KAWASAKI LSI DRIVER +P: Brad Hards +M: bradh@frogmouth.net +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained USB OHCI DRIVER P: Roman Weissgaerber diff -u --recursive --new-file v2.4.9/linux/Makefile linux/Makefile --- v2.4.9/linux/Makefile Mon Aug 27 12:41:37 2001 +++ linux/Makefile Tue Aug 28 11:27:13 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 9 -EXTRAVERSION = +SUBLEVEL = 10 +EXTRAVERSION =-pre2 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.4.9/linux/arch/alpha/kernel/alpha_ksyms.c Mon Aug 27 12:41:37 2001 +++ linux/arch/alpha/kernel/alpha_ksyms.c Mon Aug 27 07:56:48 2001 @@ -77,6 +77,14 @@ EXPORT_SYMBOL(_writeb); EXPORT_SYMBOL(_writew); EXPORT_SYMBOL(_writel); +EXPORT_SYMBOL(___raw_readb); +EXPORT_SYMBOL(___raw_readw); +EXPORT_SYMBOL(___raw_readl); +EXPORT_SYMBOL(___raw_readq); +EXPORT_SYMBOL(___raw_writeb); +EXPORT_SYMBOL(___raw_writew); +EXPORT_SYMBOL(___raw_writel); +EXPORT_SYMBOL(___raw_writeq); EXPORT_SYMBOL(_memcpy_fromio); EXPORT_SYMBOL(_memcpy_toio); EXPORT_SYMBOL(_memset_c_io); diff -u --recursive --new-file v2.4.9/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.9/linux/arch/i386/defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/i386/defconfig Mon Aug 27 09:16:06 2001 @@ -741,6 +741,7 @@ # CONFIG_USB_PLUSB is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set # CONFIG_USB_NET1080 is not set # diff -u --recursive --new-file v2.4.9/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.4.9/linux/arch/ppc/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.18 07/07/01 13:37:26 paulus +# BK Id: SCCS/s.Makefile 1.21 08/19/01 20:06:47 paulus # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions @@ -14,6 +14,7 @@ # Rewritten by Cort Dougan and Paul Mackerras # +# Be sure to change PAGE_OFFSET in include/asm-ppc/page.h to match KERNELLOAD =0xc0000000 ifeq ($(shell uname -m),ppc) @@ -99,5 +100,5 @@ archmrproper: -archdep: +archdep: scripts/mkdep $(MAKEBOOT) fastdep diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile --- v2.4.9/linux/arch/ppc/boot/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/Makefile Tue Aug 28 06:58:33 2001 @@ -12,8 +12,8 @@ GZIP_FLAGS = -v9f -CFLAGS := $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -D__BOOTER__ \ - -I$(TOPDIR)/arch/$(ARCH)/boot/include +CFLAGS += -fno-builtin -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/boot/include + AFLAGS += -D__BOOTER__ OBJCOPY_ARGS = -O elf32-powerpc diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/chrp/Makefile linux/arch/ppc/boot/chrp/Makefile --- v2.4.9/linux/arch/ppc/boot/chrp/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/chrp/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.10 07/19/01 09:11:27 trini +# BK Id: SCCS/s.Makefile 1.13 07/27/01 20:24:17 trini # # Makefile for making ELF bootable images for booting on CHRP # using Open Firmware. @@ -14,8 +14,6 @@ MSIZE= endif -CFLAGS += -fno-builtin - .c.o: $(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $< .S.o: @@ -23,7 +21,8 @@ LD_ARGS = -Ttext 0x00400000 -OBJS = ../common/crt0.o start.o main.o misc.o ../common/string.o image.o +OBJS = ../common/crt0.o start.o main.o misc.o ../common/string.o image.o \ + ../common/ofcommon.o LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a ADDNOTE = ../utils/addnote PIGGYBACK = ../utils/piggyback diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/chrp/main.c linux/arch/ppc/boot/chrp/main.c --- v2.4.9/linux/arch/ppc/boot/chrp/main.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/chrp/main.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.main.c 1.9 06/12/01 16:42:26 paulus + * BK Id: SCCS/s.main.c 1.13 07/27/01 20:24:17 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -10,14 +10,28 @@ * 2 of the License, or (at your option) any later version. */ #include "nonstdio.h" -#include "zlib.h" -#include #include -#include -extern void *finddevice(const char *); +extern char _end[]; +extern char initrd_data[]; +extern char image_data[]; +extern char sysmap_data[]; extern int getprop(void *, const char *, void *, int); -void gunzip(void *, int, unsigned char *, int *); +extern int initrd_len; +extern int image_len; +extern int sysmap_len; +extern unsigned int heap_max; +extern void claim(unsigned int virt, unsigned int size, unsigned int align); +extern void *finddevice(const char *); +extern void flush_cache(void *, unsigned long); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void pause(void); + +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; #define RAM_START 0x00000000 #define RAM_END (64<<20) @@ -27,38 +41,28 @@ #define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF) #define PROG_START 0x00010000 +#define PROG_SIZE 0x00400000 /* 4MB */ -char *avail_ram; -char *end_avail; - -extern char _end[]; -extern char image_data[]; -extern int image_len; -extern char initrd_data[]; -extern int initrd_len; -extern char sysmap_data[]; -extern int sysmap_len; +#define SCRATCH_SIZE (128 << 10) -static char scratch[1024<<10]; /* 1MB of scratch space for gunzip */ +static char scratch[SCRATCH_SIZE]; /* 1MB of scratch space for gunzip */ +void chrpboot(int a1, int a2, void *prom) { - int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; - unsigned initrd_start, initrd_size; + unsigned initrd_start=0, initrd_size=0; extern char _start; - printf("chrpboot starting: loaded at 0x%x\n\r", &_start); + printf("chrpboot starting: loaded at 0x%p\n\r", &_start); if (initrd_len) { initrd_size = initrd_len; initrd_start = (RAM_END - initrd_size) & ~0xFFF; - a1 = initrd_start; - a2 = initrd_size; claim(initrd_start, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r", + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", initrd_start, initrd_data, initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); } @@ -66,133 +70,31 @@ im = image_data; len = image_len; /* claim 4MB starting at PROG_START */ - claim(PROG_START, (4<<20) - PROG_START, 0); + claim(PROG_START, PROG_SIZE - PROG_START, 0); dst = (void *) PROG_START; if (im[0] == 0x1f && im[1] == 0x8b) { avail_ram = scratch; + begin_avail = avail_high = avail_ram; end_avail = scratch + sizeof(scratch); - printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); gunzip(dst, 0x400000, im, &len); printf("done %u bytes\n\r", len); + printf("%u bytes of heap consumed, max in use %u\n\r", + avail_high - begin_avail, heap_max); } else { memmove(dst, im, len); } flush_cache(dst, len); + make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp, + (PROG_START + PROG_SIZE)); sa = (unsigned long)PROG_START; printf("start address = 0x%x\n\r", sa); - { - struct bi_record *rec; - - rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20)); - - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - 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->tag = BI_MACHTYPE; - rec->data[0] = _MACH_chrp; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->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) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -#endif - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - } - (*(void (*)())sa)(a1, a2, prom); + (*(void (*)())sa)(a1, a2, prom, initrd_start, initrd_size); printf("returned?\n\r"); pause(); -} - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p = avail_ram; - - size *= items; - size = (size + 7) & -8; - avail_ram += size; - if (avail_ram > end_avail) { - printf("oops... out of memory\n\r"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - nb = (nb + 7) & -8; - if (addr == (avail_ram - nb)) { - avail_ram -= nb; - } -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n\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); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/chrp/start.c linux/arch/ppc/boot/chrp/start.c --- v2.4.9/linux/arch/ppc/boot/chrp/start.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/chrp/start.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.start.c 1.6 05/18/01 15:16:59 cort + * BK Id: SCCS/s.start.c 1.8 07/25/01 18:13:07 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -24,6 +24,9 @@ void printk(char *fmt, ...); +extern void chrpboot(int a1, int a2, void *prom); +extern int strlen(const char *s); + void start(int a1, int a2, void *promptr) { @@ -91,7 +94,7 @@ } void -exit() +exit(void) { struct prom_args { char *service; @@ -104,7 +107,7 @@ } void -pause() +pause(void) { struct prom_args { char *service; @@ -228,7 +231,7 @@ static int lineleft; int -getchar() +getchar(void) { int c; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/crt0.S linux/arch/ppc/boot/common/crt0.S --- v2.4.9/linux/arch/ppc/boot/common/crt0.S Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/crt0.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.crt0.S 1.10 05/21/01 00:49:49 cort + * BK Id: SCCS/s.crt0.S 1.12 08/09/01 17:09:10 paulus */ /* Copyright (c) 1997 Paul Mackerras * Initial Power Macintosh COFF version. @@ -34,7 +34,21 @@ .globl __start __start: #endif -#ifdef CONFIG_4xx + + ## Flush and invalidate the caches for the range in memory covering + ## the .text section of the boot loader + + lis r9,_start@h # r9 = &_start + lis r8,_etext@ha # + addi r8,r8,_etext@l # r8 = &_etext +3: dcbf r0,r9 # Flush the data cache + icbi r0,r9 # Invalidate the instruction cache + addi r9,r9,0x10 # Increment by one cache line + cmplw cr0,r9,r8 # Are we at the end yet? + blt 3b # No, keep flushing and invalidating + sync # sync ; isync after flushing the icache + isync + ## Clear out the BSS as per ANSI C requirements lis r7,_end@ha @@ -53,21 +67,7 @@ li r0,0 # r0 = 0 1: stwu r0,4(r8) # Clear out a word bdnz 1b # If we are not done yet, keep clearing -#endif - - ## Flush and invalidate the caches for the range in memory covering - ## the .text section of the boot loader - -2: lis r9,_start@h # r9 = &_start - lis r8,_etext@ha # - addi r8,r8,_etext@l # r8 = &_etext -3: dcbf r0,r9 # Flush the data cache - icbi r0,r9 # Invalidate the instruction cache - addi r9,r9,0x10 # Increment by one cache line - cmplw cr0,r9,r8 # Are we at the end yet? - blt 3b # No, keep flushing and invalidating - sync # sync ; isync after flushing the icache - isync +2: #ifdef CONFIG_4xx ## Set up the stack diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/misc-common.c linux/arch/ppc/boot/common/misc-common.c --- v2.4.9/linux/arch/ppc/boot/common/misc-common.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/common/misc-common.c Tue Aug 28 06:58:33 2001 @@ -31,9 +31,10 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include /* for va_ bits */ #include #include "zlib.h" -#include +#include "nonstdio.h" /* If we're on a ALL_PPC, assume we have a keyboard controller * Also note, if we're not ALL_PPC, we assume you are a serial @@ -71,14 +72,15 @@ void gunzip(void *, int, unsigned char *, int *); static int _cvt(unsigned long val, char *buf, long radix, char *digits); -void _vprintk(void(*)(const char), const char *, va_list); +void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap); +unsigned char *ISA_io = NULL; #if defined(CONFIG_SERIAL_CONSOLE) extern unsigned long com_port; -extern int serial_tstc(volatile unsigned long com_port); -extern unsigned char serial_getc(volatile unsigned long com_port); -extern void serial_putc(volatile unsigned long com_port, unsigned char c); +extern int serial_tstc(unsigned long com_port); +extern unsigned char serial_getc(unsigned long com_port); +extern void serial_putc(unsigned long com_port, unsigned char c); #endif void pause(void) @@ -301,7 +303,6 @@ #define FALSE 0 #define TRUE 1 -#include void _printk(char const *fmt, ...) @@ -528,6 +529,28 @@ { _printk("\n"); _dump_buf_with_offset(p, s, 0); +} + +/* Very simple inb/outb routines. We declare ISA_io to be 0 above, and + * then modify it on platforms which need to. We do it like this + * because on some platforms we give inb/outb an exact location, and + * on others it's an offset from a given location. -- Tom + */ + +void +outb(int port, unsigned char val) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + ISA_io[port] = val; +} + +unsigned char +inb(int port) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + return (ISA_io[port]); } /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/misc-simple.c linux/arch/ppc/boot/common/misc-simple.c --- v2.4.9/linux/arch/ppc/boot/common/misc-simple.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/misc-simple.c Tue Aug 28 06:58:33 2001 @@ -26,6 +26,7 @@ #include #include +#include "nonstdio.h" #include "zlib.h" unsigned long com_port; @@ -47,16 +48,8 @@ char *zimage_start; int zimage_size; -extern void puts(const char *); -extern void putc(const char c); -extern void puthex(unsigned long val); -extern void *memcpy(void * __dest, __const void * __src, - __kernel_size_t __n); extern void gunzip(void *, int, unsigned char *, int *); -extern void udelay(long delay); -extern int tstc(void); -extern int getc(void); -extern volatile unsigned long serial_init(int chan); +extern unsigned long serial_init(int chan); void decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/ns16550.c linux/arch/ppc/boot/common/ns16550.c --- v2.4.9/linux/arch/ppc/boot/common/ns16550.c Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/common/ns16550.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ns16550.c 1.7 05/18/01 06:20:29 patch + * BK Id: SCCS/s.ns16550.c 1.9 07/30/01 17:19:40 trini */ /* * COM1 NS16550 support @@ -10,12 +10,9 @@ #include #include -/* Some machines, such as ones with a PReP memory map, initally have - * their serial port at an offset of 0x80000000 from where they are - * in . This tries to take that into account. */ -#ifndef IOOFFSET -#define IOOFFSET 0 -#endif +extern void outb(int port, unsigned char val); +extern unsigned char inb(int port); +extern unsigned long ISA_io; static struct serial_state rs_table[RS_TABLE_SIZE] = { SERIAL_PORT_DFNS /* Defined in */ @@ -23,58 +20,67 @@ static int shift; -volatile unsigned long serial_init(int chan) { +unsigned long serial_init(int chan) { unsigned long com_port; - /* Get the base, and add any offset we need to deal with. */ - com_port = rs_table[chan].port + IOOFFSET; + /* We need to find out which type io we're expecting. If it's + * 'SERIAL_IO_PORT', we get an offset from the isa_io_base. + * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */ + switch (rs_table[chan].io_type) { + case SERIAL_IO_PORT: + com_port = rs_table[chan].port; + break; + case SERIAL_IO_MEM: + com_port = (unsigned long)rs_table[chan].iomem_base; + break; + default: + /* We can't deal with it. */ + return -1; + } /* How far apart the registers are. */ shift = rs_table[chan].iomem_reg_shift; /* See if port is present */ - *((unsigned char *)com_port + (UART_LCR << shift)) = 0x00; - *((unsigned char *)com_port + (UART_IER << shift)) = 0x00; + outb(com_port + (UART_LCR << shift), 0x00); + outb(com_port + (UART_IER << shift), 0x00); /* Access baud rate */ - *((unsigned char *)com_port + (UART_LCR << shift)) = 0x00; + outb(com_port + (UART_LCR << shift), 0x80); #ifdef CONFIG_SERIAL_CONSOLE_NONSTD /* Input clock. */ - *((unsigned char *)com_port + (UART_DLL << shift)) = - (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD); - *((unsigned char *)com_port + (UART_DLM << shift)) = - (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8; + outb(com_port + (UART_DLL << shift), + (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD)); + outb(com_port + (UART_DLM << shift), + (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8); #endif /* 8 data, 1 stop, no parity */ - *((unsigned char *)com_port + (UART_LCR << shift)) = 0x03; + outb(com_port + (UART_LCR << shift), 0x03); /* RTS/DTR */ - *((unsigned char *)com_port + (UART_MCR << shift)) = 0x03; + outb(com_port + (UART_MCR << shift), 0x03); /* Clear & enable FIFOs */ - *((unsigned char *)com_port + (UART_FCR << shift)) = 0x07; + outb(com_port + (UART_FCR << shift), 0x07); return (com_port); } void -serial_putc(volatile unsigned long com_port, unsigned char c) +serial_putc(unsigned long com_port, unsigned char c) { - while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) & - UART_LSR_THRE) == 0) + while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0) ; - *(volatile unsigned char *)com_port = c; + outb(com_port, c); } unsigned char -serial_getc(volatile unsigned long com_port) +serial_getc(unsigned long com_port) { - while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) - & UART_LSR_DR) == 0) + while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0) ; - return (*(volatile unsigned char *)com_port); + return inb(com_port); } int -serial_tstc(volatile unsigned long com_port) +serial_tstc(unsigned long com_port) { - return ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) - & UART_LSR_DR) != 0); + return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/common/ofcommon.c linux/arch/ppc/boot/common/ofcommon.c --- v2.4.9/linux/arch/ppc/boot/common/ofcommon.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/boot/common/ofcommon.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,171 @@ +/* + * BK Id: SCCS/s.ofcommon.c 1.1 07/27/01 20:24:18 trini + * + * Copyright (C) Paul Mackerras 1997. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "zlib.h" +#include "nonstdio.h" +#include +#include + +extern int strcmp(const char *s1, const char *s2); +extern char *avail_ram, *avail_high; +extern char *end_avail; +extern void claim(unsigned int virt, unsigned int size, unsigned int align); +extern void pause(void); + +unsigned int heap_use, heap_max; + +struct memchunk { + unsigned int size; + struct memchunk *next; +}; + +static struct memchunk *freechunks; + +static void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p; + struct memchunk **mpp, *mp; + + size *= items; + size = (size + 7) & -8; + heap_use += size; + if (heap_use > heap_max) + heap_max = heap_use; + for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { + if (mp->size == size) { + *mpp = mp->next; + return mp; + } + } + p = avail_ram; + avail_ram += size; + if (avail_ram > avail_high) + avail_high = avail_ram; + if (avail_ram > end_avail) { + printf("oops... out of memory\n\r"); + pause(); + } + return p; +} + +static void zfree(void *x, void *addr, unsigned nb) +{ + struct memchunk *mp = addr; + + nb = (nb + 7) & -8; + heap_use -= nb; + if (avail_ram == addr + nb) { + avail_ram = addr; + return; + } + mp->size = nb; + mp->next = freechunks; + freechunks = mp; +} + +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +#define DEFLATED 8 + +void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + printf("bad gzipped data\n\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); +} + +/* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID, + * a machine type for BI_MACHTYPE, and the location where the end of the + * bootloader is (PROG_START + PROG_SIZE) + */ +void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned long progend) +{ + struct bi_record *rec; + + /* leave a 1MB gap then align to the next 1MB boundary */ + addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); + /* oldworld machine seem very unhappy about this. -- Tom */ + if (addr >= progend) + claim(addr, 0x1000, 0); + + rec = (struct bi_record *)addr; + rec->tag = BI_FIRST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_BOOTLOADER_ID; + sprintf( (char *)rec->data, name); + rec->size = sizeof(struct bi_record) + strlen(name) + 1; + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + rec->tag = BI_MACHTYPE; + rec->data[0] = mach; + rec->data[1] = 1; + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); + rec = (struct bi_record *)((unsigned long)rec + rec->size); + +#ifdef SYSMAP_OFFSET + rec->tag = BI_SYSMAP; + rec->data[0] = SYSMAP_OFFSET; + rec->data[1] = SYSMAP_SIZE; + rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); + rec = (struct bi_record *)((unsigned long)rec + rec->size); +#endif /* SYSMAP_OFFSET */ + + rec->tag = BI_LAST; + rec->size = sizeof(struct bi_record); + rec = (struct bi_record *)((unsigned long)rec + rec->size); +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/include/nonstdio.h linux/arch/ppc/boot/include/nonstdio.h --- v2.4.9/linux/arch/ppc/boot/include/nonstdio.h Thu May 24 15:02:06 2001 +++ linux/arch/ppc/boot/include/nonstdio.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.nonstdio.h 1.7 05/18/01 15:17:23 cort + * BK Id: SCCS/s.nonstdio.h 1.9 07/25/01 18:13:07 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -8,14 +8,31 @@ * 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 is sort of a catchall for I/O related functions. Stuff that + * wouldn't be in 'stdio.h' normally is here, and it's 'nonstdio.h' + * for a reason. -- Tom */ -typedef int FILE; +typedef int FILE; extern FILE *stdin, *stdout; -#define NULL ((void *)0) -#define EOF (-1) -#define fopen(n, m) NULL -#define fflush(f) 0 -#define fclose(f) 0 -extern char *fgets(); +#define NULL ((void *)0) +#define EOF (-1) +#define fopen(n, m) NULL +#define fflush(f) 0 +#define fclose(f) 0 +#define perror(s) printf("%s: no files!\n", (s)) -#define perror(s) printf("%s: no files!\n", (s)) +extern int getc(void); +extern int printf(const char *format, ...); +extern int strlen(const char *s); +extern int sprintf(char *str, const char *format, ...); +extern int tstc(void); +extern void exit(void); +extern void *memcpy(void *dest, const void *src, int n); +extern void *memmove(void *dest, const void *src, int n); +extern void outb(int port, unsigned char val); +extern void putc(const char c); +extern void puthex(unsigned long val); +extern void puts(const char *); +extern void udelay(long delay); +extern unsigned char inb(int port); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/mbx/misc.c linux/arch/ppc/boot/mbx/misc.c --- v2.4.9/linux/arch/ppc/boot/mbx/misc.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/mbx/misc.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.misc.c 1.11 07/18/01 15:46:50 trini + * BK Id: SCCS/s.misc.c 1.13 07/27/01 11:44:37 trini */ /* * Adapted for PowerPC by Gary Thomas @@ -23,6 +23,8 @@ #include #endif +#include "nonstdio.h" + /* * The following references are needed to cause the linker to pull in the * gzimage.o and rdimage.o files. These object files are special, @@ -75,14 +77,7 @@ char *zimage_start; int zimage_size; -extern void puts(const char *); -extern void putc(const char c); -extern void udelay(long x); -extern void puthex(unsigned long val); -extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n); extern void gunzip(void *, int, unsigned char *, int *); -extern int tstc(void); -extern int getc(void); unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) @@ -267,33 +262,4 @@ puts("done.\n"); puts("Now booting the kernel\n"); return (unsigned long)hold_residual; -} - -/* - * PCI/ISA I/O support - */ - -volatile unsigned char *ISA_io = (unsigned char *)0x80000000; -volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000; - -void -outb(int port, char val) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - ISA_io[port] = val; -} - -unsigned char -inb(int port) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - return (ISA_io[port]); -} - -unsigned long -local_to_PCI(unsigned long addr) -{ - return ((addr & 0x7FFFFFFF) | 0x80000000); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/Makefile linux/arch/ppc/boot/pmac/Makefile --- v2.4.9/linux/arch/ppc/boot/pmac/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/pmac/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.12 07/19/01 09:11:28 trini +# BK Id: SCCS/s.Makefile 1.14 07/27/01 20:24:17 trini # # Makefile for making XCOFF bootable images for booting on PowerMacs # using Open Firmware. @@ -12,12 +12,10 @@ COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic CHRP_LD_ARGS = -Ttext 0x01000000 -COMMONOBJS = start.o misc.o ../common/string.o image.o +COMMONOBJS = start.o misc.o ../common/string.o image.o ../common/ofcommon.o COFFOBJS = ../common/coffcrt0.o $(COMMONOBJS) coffmain.o CHRPOBJS = ../common/crt0.o $(COMMONOBJS) chrpmain.o LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a - -CFLAGS += -fno-builtin MKNOTE := ../utils/mknote SIZE := ../utils/size diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/chrpmain.c linux/arch/ppc/boot/pmac/chrpmain.c --- v2.4.9/linux/arch/ppc/boot/pmac/chrpmain.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/pmac/chrpmain.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrpmain.c 1.12 06/12/01 16:42:26 paulus + * BK Id: SCCS/s.chrpmain.c 1.16 07/27/01 20:24:18 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -11,21 +11,26 @@ */ #include "nonstdio.h" #include "zlib.h" -#include #include -#include -extern void *finddevice(const char *); +extern char _end[]; +extern char image_data[], initrd_data[]; +extern int image_len, initrd_len; extern int getprop(void *, const char *, void *, int); +extern unsigned int heap_max; extern void *claim(unsigned int, unsigned int, unsigned int); +extern void *finddevice(const char *); +extern void flush_cache(void *start, unsigned int len); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void pause(void); extern void release(void *ptr, unsigned int len); -void make_bi_recs(unsigned long); -void gunzip(void *, int, unsigned char *, int *); -void stop_imac_ethernet(void); -void stop_imac_usb(void); -#define get_16be(x) (*(unsigned short *)(x)) -#define get_32be(x) (*(unsigned *)(x)) +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; + #define RAM_END (16 << 20) @@ -34,36 +39,22 @@ #define SCRATCH_SIZE (128 << 10) -char *avail_ram; -char *begin_avail, *end_avail; -char *avail_high; -unsigned int heap_use; -unsigned int heap_max; - -extern char _end[]; -extern char image_data[]; -extern int image_len; -extern char initrd_data[]; -extern int initrd_len; - - -boot(int a1, int a2, void *prom) +void boot(int a1, int a2, void *prom) { - int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; unsigned initrd_start, initrd_size; extern char _start; - printf("chrpboot starting: loaded at 0x%x\n", &_start); + printf("chrpboot starting: loaded at 0x%p\n", &_start); if (initrd_len) { initrd_size = initrd_len; initrd_start = (RAM_END - initrd_size) & ~0xFFF; a1 = initrd_start; a2 = initrd_size; claim(initrd_start, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n", initrd_start, + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n", initrd_start, initrd_data,initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); } @@ -77,8 +68,8 @@ avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10); begin_avail = avail_high = avail_ram; end_avail = avail_ram + SCRATCH_SIZE; - printf("heap at 0x%x\n", avail_ram); - printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); + printf("heap at 0x%p\n", avail_ram); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); gunzip(dst, PROG_SIZE, im, &len); printf("done %u bytes\n", len); printf("%u bytes of heap consumed, max in use %u\n", @@ -89,7 +80,8 @@ } flush_cache(dst, len); - make_bi_recs((unsigned long) dst + len); + make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac, + (PROG_START + PROG_SIZE)); sa = (unsigned long)PROG_START; printf("start address = 0x%x\n", sa); @@ -99,199 +91,4 @@ printf("returned?\n"); pause(); -} - -void make_bi_recs(unsigned long addr) -{ - struct bi_record *rec; - - /* leave a 1MB gap then align to the next 1MB boundary */ - addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); - if (addr >= PROG_START + PROG_SIZE) - claim(addr, 0x1000, 0); - - rec = (struct bi_record *)addr; - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - sprintf( (char *)rec->data, "coffboot"); - rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_Pmac; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - -#ifdef SYSMAP_OFFSET - rec->tag = BI_SYSMAP; - rec->data[0] = SYSMAP_OFFSET; - rec->data[1] = SYSMAP_SIZE; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -#endif /* SYSMAP_OFFSET */ - - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -} - -#if 0 -#define eieio() asm volatile("eieio"); - -void stop_imac_ethernet(void) -{ - void *macio, *enet; - unsigned int macio_addr[5], enet_reg[6]; - int len; - volatile unsigned int *dbdma; - - macio = finddevice("/pci/mac-io"); - enet = finddevice("/pci/mac-io/ethernet"); - if (macio == NULL || enet == NULL) - return; - len = getprop(macio, "assigned-addresses", macio_addr, sizeof(macio_addr)); - if (len != sizeof(macio_addr)) - return; - len = getprop(enet, "reg", enet_reg, sizeof(enet_reg)); - if (len != sizeof(enet_reg)) - return; - printf("macio base %x, dma at %x & %x\n", - macio_addr[2], enet_reg[2], enet_reg[4]); - - /* hope this is mapped... */ - dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[2]); - *dbdma = 0x80; /* clear the RUN bit */ - eieio(); - dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[4]); - *dbdma = 0x80; /* clear the RUN bit */ - eieio(); -} - -void stop_imac_usb(void) -{ - void *usb; - unsigned int usb_addr[5]; - int len; - volatile unsigned int *usb_ctrl; - - usb = finddevice("/pci/usb"); - if (usb == NULL) - return; - len = getprop(usb, "assigned-addresses", usb_addr, sizeof(usb_addr)); - if (len != sizeof(usb_addr)) - return; - printf("usb base %x\n", usb_addr[2]); - - usb_ctrl = (volatile unsigned int *) (usb_addr[2] + 8); - *usb_ctrl = 0x01000000; /* cpu_to_le32(1) */ - eieio(); -} -#endif - -struct memchunk { - unsigned int size; - struct memchunk *next; -}; - -static struct memchunk *freechunks; - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - struct memchunk **mpp, *mp; - - size *= items; - size = (size + 7) & -8; - heap_use += size; - if (heap_use > heap_max) - heap_max = heap_use; - for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { - if (mp->size == size) { - *mpp = mp->next; - return mp; - } - } - p = avail_ram; - avail_ram += size; - if (avail_ram > avail_high) - avail_high = avail_ram; - if (avail_ram > end_avail) { - printf("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - struct memchunk *mp = addr; - - nb = (nb + 7) & -8; - heap_use -= nb; - if (avail_ram == addr + nb) { - avail_ram = addr; - return; - } - mp->size = nb; - mp->next = freechunks; - freechunks = mp; -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/coffmain.c linux/arch/ppc/boot/pmac/coffmain.c --- v2.4.9/linux/arch/ppc/boot/pmac/coffmain.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/pmac/coffmain.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.coffmain.c 1.12 06/12/01 16:42:26 paulus + * BK Id: SCCS/s.coffmain.c 1.14 07/27/01 20:24:18 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -11,18 +11,25 @@ */ #include "nonstdio.h" #include "zlib.h" -#include #include -#include -extern void *finddevice(const char *); -extern int getprop(void *, const char *, void *, int); +extern char _start[], _end[]; extern char *claim(unsigned, unsigned, unsigned); -void make_bi_recs(unsigned long); -void gunzip(void *, int, unsigned char *, int *); +extern char image_data[], initrd_data[]; +extern int initrd_len, image_len; +extern int getprop(void *, const char *, void *, int); +extern unsigned int heap_max; +extern void *finddevice(const char *); +extern void flush_cache(void *start, unsigned int len); +extern void gunzip(void *, int, unsigned char *, int *); +extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, + unsigned int progend); +extern void pause(void); +extern void setup_bats(unsigned long start); -#define get_16be(x) (*(unsigned short *)(x)) -#define get_32be(x) (*(unsigned *)(x)) +char *avail_ram; +char *begin_avail, *end_avail; +char *avail_high; #define RAM_START 0 #define RAM_END (RAM_START + 0x800000) /* only 8M mapped with BATs */ @@ -32,29 +39,16 @@ #define SCRATCH_SIZE (128 << 10) -char *avail_ram; -char *begin_avail, *end_avail; -char *avail_high; -unsigned int heap_use; -unsigned int heap_max; - -extern char _start[], _end[]; -extern char image_data[]; -extern int image_len; -extern char initrd_data[]; -extern int initrd_len; +static char heap[SCRATCH_SIZE]; -char heap[SCRATCH_SIZE]; - -boot(int a1, int a2, void *prom) +void boot(int a1, int a2, void *prom) { - int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; unsigned initrd_start, initrd_size; - printf("coffboot starting: loaded at 0x%x\n", _start); + printf("coffboot starting: loaded at 0x%p\n", &_start); setup_bats(RAM_START); if (initrd_len) { initrd_size = initrd_len; @@ -62,21 +56,21 @@ a1 = initrd_start; a2 = initrd_size; claim(initrd_start - RAM_START, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n", + printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n", initrd_start, initrd_data, initrd_size); memcpy((char *)initrd_start, initrd_data, initrd_size); } im = image_data; len = image_len; - /* claim 3MB starting at 0 */ + /* claim 4MB starting at 0 */ claim(0, PROG_SIZE, 0); dst = (void *) RAM_START; if (im[0] == 0x1f && im[1] == 0x8b) { /* set up scratch space */ begin_avail = avail_high = avail_ram = heap; end_avail = heap + sizeof(heap); - printf("heap at 0x%x\n", avail_ram); - printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); + printf("heap at 0x%p\n", avail_ram); + printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); gunzip(dst, PROG_SIZE, im, &len); printf("done %u bytes\n", len); printf("%u bytes of heap consumed, max in use %u\n", @@ -86,8 +80,9 @@ } flush_cache(dst, len); - make_bi_recs((unsigned long)dst + len); - + make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac, + (PROG_START + PROG_SIZE)); + sa = (unsigned long)PROG_START; printf("start address = 0x%x\n", sa); @@ -96,139 +91,4 @@ printf("returned?\n"); pause(); -} - -void make_bi_recs(unsigned long addr) -{ - struct bi_record *rec; - - addr = _ALIGN(addr+ (1<<20) - 1, (1<<20)); -#if 0 - if (addr >= PROG_START + PROG_SIZE) - claim(addr, 0x1000, 0); -#endif - - rec = (struct bi_record *)addr; - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - sprintf( (char *)rec->data, "coffboot"); - rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MACHTYPE; - rec->data[0] = _MACH_Pmac; - rec->data[1] = 1; - rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); -} - -struct memchunk { - unsigned int size; - struct memchunk *next; -}; - -static struct memchunk *freechunks; - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - struct memchunk **mpp, *mp; - - size *= items; - size = (size + 7) & -8; - heap_use += size; - if (heap_use > heap_max) - heap_max = heap_use; - for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { - if (mp->size == size) { - *mpp = mp->next; - return mp; - } - } - p = avail_ram; - avail_ram += size; - if (avail_ram > avail_high) - avail_high = avail_ram; - if (avail_ram > end_avail) { - printf("oops... out of memory\n"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - struct memchunk *mp = addr; - - nb = (nb + 7) & -8; - heap_use -= nb; - if (avail_ram == addr + nb) { - avail_ram = addr; - return; - } - mp->size = nb; - mp->next = freechunks; - freechunks = mp; -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n"); - exit(); - } - - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/pmac/start.c linux/arch/ppc/boot/pmac/start.c --- v2.4.9/linux/arch/ppc/boot/pmac/start.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/pmac/start.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.start.c 1.8 05/18/01 15:17:15 cort + * BK Id: SCCS/s.start.c 1.10 07/25/01 18:13:07 trini */ /* * Copyright (C) Paul Mackerras 1997. @@ -11,6 +11,9 @@ */ #include +extern int strlen(const char *s); +extern void boot(int a1, int a2, void *prom); + int (*prom)(); void *chosen_handle; @@ -109,7 +112,7 @@ } void -exit() +exit(void) { struct prom_args { char *service; @@ -122,7 +125,7 @@ } void -pause() +pause(void) { struct prom_args { char *service; @@ -243,7 +246,7 @@ } int -readchar() +readchar(void) { char ch; @@ -263,7 +266,7 @@ static int lineleft; int -getchar() +getchar(void) { int c; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/Makefile linux/arch/ppc/boot/prep/Makefile --- v2.4.9/linux/arch/ppc/boot/prep/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/boot/prep/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.19 07/19/01 09:11:28 trini +# BK Id: SCCS/s.Makefile 1.24 08/01/01 13:25:40 trini # # arch/ppc/boot/Makefile # @@ -17,8 +17,6 @@ USE_STANDARD_AS_RULE := true -CFLAGS += -fno-builtin - ifeq ($(CONFIG_SMP),y) TFTPIMAGE = /tftpboot/zImage.prep.smp else @@ -32,7 +30,7 @@ OBJCOPY_ARGS = -O elf32-powerpc LIBS = ../lib/zlib.a -obj-$(CONFIG_SERIAL_CONSOLE) += ns16550.o +obj-$(CONFIG_SERIAL_CONSOLE) += ../common/ns16550.o obj-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o # Tools @@ -45,9 +43,6 @@ misc.o: misc.c $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \ -DZIMAGE_SIZE=0 -c -o $@ $*.c - -ns16550.o: ../common/ns16550.c - $(CC) $(CFLAGS) -DIOOFFSET=0x80000000 -c -o $@ ../common/$*.c zvmlinux.initrd: zvmlinux ../images/vmlinux.gz $(LD) $(ZLINKFLAGS) -o $@.tmp $(obj-y) $(LIBS) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/head.S linux/arch/ppc/boot/prep/head.S --- v2.4.9/linux/arch/ppc/boot/prep/head.S Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/prep/head.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head.S 1.8 05/18/01 06:20:29 patch + * BK Id: SCCS/s.head.S 1.11 07/31/01 16:36:06 trini */ #include "../../kernel/ppc_defs.h" #include "../../kernel/ppc_asm.tmpl" @@ -95,6 +95,11 @@ subi r1,r1,256 li r2,0x000F /* Mask pointer to 16-byte boundary */ andc r1,r1,r2 +/* Setup ISA_io */ + lis r3,ISA_io@h + ori r3,r3,ISA_io@l + lis r4,0x8000 + stw r4,0(r3) /* Run loader */ mr r3,r8 /* Load point */ mr r4,r7 /* Program length */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/misc.c linux/arch/ppc/boot/prep/misc.c --- v2.4.9/linux/arch/ppc/boot/prep/misc.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/boot/prep/misc.c Tue Aug 28 06:58:33 2001 @@ -1,8 +1,7 @@ /* - * BK Id: SCCS/s.misc.c 1.14 06/16/01 20:43:20 trini - */ -/* - * misc.c + * BK Id: SCCS/s.misc.c 1.18 07/30/01 17:19:40 trini + * + * arch/ppc/boot/prep/misc.c * * Adapted for PowerPC by Gary Thomas * @@ -11,7 +10,6 @@ */ #include -#include "zlib.h" #include #include #include @@ -22,9 +20,8 @@ #include #include #include -#if defined(CONFIG_SERIAL_CONSOLE) -unsigned long com_port; -#endif /* CONFIG_SERIAL_CONSOLE */ +#include "nonstdio.h" +#include "zlib.h" /* * Please send me load/board info and such data for hardware not @@ -53,26 +50,28 @@ char *zimage_start; int zimage_size; +#if defined(CONFIG_SERIAL_CONSOLE) +unsigned long com_port; +#endif /* CONFIG_SERIAL_CONSOLE */ +#ifdef CONFIG_VGA_CONSOLE char *vidmem = (char *)0xC00B8000; -int lines, cols; -int orig_x, orig_y; +int lines = 25, cols = 80; +int orig_x, orig_y = 24; +#endif /* CONFIG_VGA_CONSOLE */ -extern void puts(const char *); -extern void putc(const char c); -extern int tstc(void); -extern int getc(void); -extern void puthex(unsigned long val); -extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n); extern int CRT_tstc(void); extern void of_init(void *handler); extern int of_finddevice(const char *device_specifier, int *phandle); extern int of_getprop(int phandle, const char *name, void *buf, int buflen, int *size); -extern __kernel_size_t strlen(const char *s); extern int vga_init(unsigned char *ISA_mem); -extern void udelay(long x); -void gunzip(void *, int, unsigned char *, int *); -unsigned char inb(int); +extern void gunzip(void *, int, unsigned char *, int *); + +extern void _put_HID0(unsigned int val); +extern void _put_MSR(unsigned int val); +extern unsigned int _get_HID0(void); +extern unsigned int _get_MSR(void); +extern unsigned long serial_init(int chan); void writel(unsigned int val, unsigned int address) @@ -105,7 +104,7 @@ #ifdef CONFIG_VGA_CONSOLE void -scroll() +scroll(void) { int i; @@ -120,7 +119,7 @@ * Motorola dual processor platforms. */ void -park_cpus() +park_cpus(void) { volatile void (*go)(RESIDUAL *, int, int, char *, int); unsigned int i; @@ -154,11 +153,6 @@ unsigned char base_mod; int start_multi = 0; unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; - - lines = 25; - cols = 80; - orig_x = 0; - orig_y = 24; /* * IBM's have the MMU on, so we have to disable it or @@ -438,28 +432,8 @@ /* * PCI/ISA I/O support */ - -volatile unsigned char *ISA_io = (unsigned char *)0x80000000; -volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000; - -void -outb(int port, char val) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - ISA_io[port] = val; -} - -unsigned char -inb(int port) -{ - /* Ensure I/O operations complete */ - __asm__ volatile("eieio"); - return (ISA_io[port]); -} - unsigned long local_to_PCI(unsigned long addr) { - return ((addr & 0x7FFFFFFF) | 0x80000000); + return (addr | 0x80000000); } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/boot/prep/vreset.c linux/arch/ppc/boot/prep/vreset.c --- v2.4.9/linux/arch/ppc/boot/prep/vreset.c Thu May 24 15:02:07 2001 +++ linux/arch/ppc/boot/prep/vreset.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.vreset.c 1.9 05/18/01 06:20:29 patch + * BK Id: SCCS/s.vreset.c 1.11 07/25/01 18:13:07 trini */ /* * vreset.c @@ -22,12 +22,10 @@ */ #include "iso_font.h" +#include "nonstdio.h" extern char *vidmem; extern int lines, cols; -extern void udelay(long x); -extern void outb(int port, char val); -extern unsigned char inb(int port); struct VaRegs; /* @@ -43,7 +41,7 @@ void unlockVideo(int slot); void setTextRegs(struct VgaRegs *svp); void setTextCLUT(int shift); -void clearVideoMemory(); +void clearVideoMemory(void); void loadFont(unsigned char *ISA_mem); static void mdelay(int ms) @@ -59,100 +57,100 @@ #define NREGS 54 #define ENDMK 0xFFFF /* End marker */ -#define S3Vendor 0x5333 +#define S3Vendor 0x5333 #define CirrusVendor 0x1013 #define DiamondVendor 0x100E #define MatroxVendor 0x102B #define ParadiseVendor 0x101C struct VgaRegs GenVgaTextRegs[NREGS+1] = { -/* port index value */ - /* SR Regs */ - 0x3c4, 0x1, 0x0, - 0x3c4, 0x2, 0x3, - 0x3c4, 0x3, 0x0, - 0x3c4, 0x4, 0x2, - /* CR Regs */ - 0x3d4, 0x0, 0x5f, - 0x3d4, 0x1, 0x4f, - 0x3d4, 0x2, 0x50, - 0x3d4, 0x3, 0x82, - 0x3d4, 0x4, 0x55, - 0x3d4, 0x5, 0x81, - 0x3d4, 0x6, 0xbf, - 0x3d4, 0x7, 0x1f, - 0x3d4, 0x8, 0x00, - 0x3d4, 0x9, 0x4f, - 0x3d4, 0xa, 0x0d, - 0x3d4, 0xb, 0x0e, - 0x3d4, 0xc, 0x00, - 0x3d4, 0xd, 0x00, - 0x3d4, 0xe, 0x00, - 0x3d4, 0xf, 0x00, - 0x3d4, 0x10, 0x9c, - 0x3d4, 0x11, 0x8e, - 0x3d4, 0x12, 0x8f, - 0x3d4, 0x13, 0x28, - 0x3d4, 0x14, 0x1f, - 0x3d4, 0x15, 0x96, - 0x3d4, 0x16, 0xb9, - 0x3d4, 0x17, 0xa3, - /* GR Regs */ - 0x3ce, 0x0, 0x0, - 0x3ce, 0x1, 0x0, - 0x3ce, 0x2, 0x0, - 0x3ce, 0x3, 0x0, - 0x3ce, 0x4, 0x0, - 0x3ce, 0x5, 0x10, - 0x3ce, 0x6, 0xe, - 0x3ce, 0x7, 0x0, - 0x3ce, 0x8, 0xff, - ENDMK + /* port index value */ + /* SR Regs */ + { 0x3c4, 0x1, 0x0 }, + { 0x3c4, 0x2, 0x3 }, + { 0x3c4, 0x3, 0x0 }, + { 0x3c4, 0x4, 0x2 }, + /* CR Regs */ + { 0x3d4, 0x0, 0x5f }, + { 0x3d4, 0x1, 0x4f }, + { 0x3d4, 0x2, 0x50 }, + { 0x3d4, 0x3, 0x82 }, + { 0x3d4, 0x4, 0x55 }, + { 0x3d4, 0x5, 0x81 }, + { 0x3d4, 0x6, 0xbf }, + { 0x3d4, 0x7, 0x1f }, + { 0x3d4, 0x8, 0x00 }, + { 0x3d4, 0x9, 0x4f }, + { 0x3d4, 0xa, 0x0d }, + { 0x3d4, 0xb, 0x0e }, + { 0x3d4, 0xc, 0x00 }, + { 0x3d4, 0xd, 0x00 }, + { 0x3d4, 0xe, 0x00 }, + { 0x3d4, 0xf, 0x00 }, + { 0x3d4, 0x10, 0x9c }, + { 0x3d4, 0x11, 0x8e }, + { 0x3d4, 0x12, 0x8f }, + { 0x3d4, 0x13, 0x28 }, + { 0x3d4, 0x14, 0x1f }, + { 0x3d4, 0x15, 0x96 }, + { 0x3d4, 0x16, 0xb9 }, + { 0x3d4, 0x17, 0xa3 }, + /* GR Regs */ + { 0x3ce, 0x0, 0x0 }, + { 0x3ce, 0x1, 0x0 }, + { 0x3ce, 0x2, 0x0 }, + { 0x3ce, 0x3, 0x0 }, + { 0x3ce, 0x4, 0x0 }, + { 0x3ce, 0x5, 0x10 }, + { 0x3ce, 0x6, 0xe }, + { 0x3ce, 0x7, 0x0 }, + { 0x3ce, 0x8, 0xff }, + { ENDMK } }; struct VgaRegs S3TextRegs[NREGS+1] = { -/* port index value */ - /* SR Regs */ - 0x3c4, 0x1, 0x0, - 0x3c4, 0x2, 0x3, - 0x3c4, 0x3, 0x0, - 0x3c4, 0x4, 0x2, - /* CR Regs */ - 0x3d4, 0x0, 0x5f, - 0x3d4, 0x1, 0x4f, - 0x3d4, 0x2, 0x50, - 0x3d4, 0x3, 0x82, - 0x3d4, 0x4, 0x55, - 0x3d4, 0x5, 0x81, - 0x3d4, 0x6, 0xbf, - 0x3d4, 0x7, 0x1f, - 0x3d4, 0x8, 0x00, - 0x3d4, 0x9, 0x4f, - 0x3d4, 0xa, 0x0d, - 0x3d4, 0xb, 0x0e, - 0x3d4, 0xc, 0x00, - 0x3d4, 0xd, 0x00, - 0x3d4, 0xe, 0x00, - 0x3d4, 0xf, 0x00, - 0x3d4, 0x10, 0x9c, - 0x3d4, 0x11, 0x8e, - 0x3d4, 0x12, 0x8f, - 0x3d4, 0x13, 0x28, - 0x3d4, 0x14, 0x1f, - 0x3d4, 0x15, 0x96, - 0x3d4, 0x16, 0xb9, - 0x3d4, 0x17, 0xa3, - /* GR Regs */ - 0x3ce, 0x0, 0x0, - 0x3ce, 0x1, 0x0, - 0x3ce, 0x2, 0x0, - 0x3ce, 0x3, 0x0, - 0x3ce, 0x4, 0x0, - 0x3ce, 0x5, 0x10, - 0x3ce, 0x6, 0xe, - 0x3ce, 0x7, 0x0, - 0x3ce, 0x8, 0xff, - ENDMK + /* port index value */ + /* SR Regs */ + { 0x3c4, 0x1, 0x0 }, + { 0x3c4, 0x2, 0x3 }, + { 0x3c4, 0x3, 0x0 }, + { 0x3c4, 0x4, 0x2 }, + /* CR Regs */ + { 0x3d4, 0x0, 0x5f }, + { 0x3d4, 0x1, 0x4f }, + { 0x3d4, 0x2, 0x50 }, + { 0x3d4, 0x3, 0x82 }, + { 0x3d4, 0x4, 0x55 }, + { 0x3d4, 0x5, 0x81 }, + { 0x3d4, 0x6, 0xbf }, + { 0x3d4, 0x7, 0x1f }, + { 0x3d4, 0x8, 0x00 }, + { 0x3d4, 0x9, 0x4f }, + { 0x3d4, 0xa, 0x0d }, + { 0x3d4, 0xb, 0x0e }, + { 0x3d4, 0xc, 0x00 }, + { 0x3d4, 0xd, 0x00 }, + { 0x3d4, 0xe, 0x00 }, + { 0x3d4, 0xf, 0x00 }, + { 0x3d4, 0x10, 0x9c }, + { 0x3d4, 0x11, 0x8e }, + { 0x3d4, 0x12, 0x8f }, + { 0x3d4, 0x13, 0x28 }, + { 0x3d4, 0x14, 0x1f }, + { 0x3d4, 0x15, 0x96 }, + { 0x3d4, 0x16, 0xb9 }, + { 0x3d4, 0x17, 0xa3 }, + /* GR Regs */ + { 0x3ce, 0x0, 0x0 }, + { 0x3ce, 0x1, 0x0 }, + { 0x3ce, 0x2, 0x0 }, + { 0x3ce, 0x3, 0x0 }, + { 0x3ce, 0x4, 0x0 }, + { 0x3ce, 0x5, 0x10 }, + { 0x3ce, 0x6, 0xe }, + { 0x3ce, 0x7, 0x0 }, + { 0x3ce, 0x8, 0xff }, + { ENDMK } }; struct RGBColors @@ -167,262 +165,262 @@ */ struct RGBColors TextCLUT[256] = { - /* red green blue */ - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x2a, - 0x0, 0x2a, 0x0, - 0x0, 0x2a, 0x2a, - 0x2a, 0x0, 0x0, - 0x2a, 0x0, 0x2a, - 0x2a, 0x2a, 0x0, - 0x2a, 0x2a, 0x2a, - 0x0, 0x0, 0x15, - 0x0, 0x0, 0x3f, - 0x0, 0x2a, 0x15, - 0x0, 0x2a, 0x3f, - 0x2a, 0x0, 0x15, - 0x2a, 0x0, 0x3f, - 0x2a, 0x2a, 0x15, - 0x2a, 0x2a, 0x3f, - 0x0, 0x15, 0x0, - 0x0, 0x15, 0x2a, - 0x0, 0x3f, 0x0, - 0x0, 0x3f, 0x2a, - 0x2a, 0x15, 0x0, - 0x2a, 0x15, 0x2a, - 0x2a, 0x3f, 0x0, - 0x2a, 0x3f, 0x2a, - 0x0, 0x15, 0x15, - 0x0, 0x15, 0x3f, - 0x0, 0x3f, 0x15, - 0x0, 0x3f, 0x3f, - 0x2a, 0x15, 0x15, - 0x2a, 0x15, 0x3f, - 0x2a, 0x3f, 0x15, - 0x2a, 0x3f, 0x3f, - 0x15, 0x0, 0x0, - 0x15, 0x0, 0x2a, - 0x15, 0x2a, 0x0, - 0x15, 0x2a, 0x2a, - 0x3f, 0x0, 0x0, - 0x3f, 0x0, 0x2a, - 0x3f, 0x2a, 0x0, - 0x3f, 0x2a, 0x2a, - 0x15, 0x0, 0x15, - 0x15, 0x0, 0x3f, - 0x15, 0x2a, 0x15, - 0x15, 0x2a, 0x3f, - 0x3f, 0x0, 0x15, - 0x3f, 0x0, 0x3f, - 0x3f, 0x2a, 0x15, - 0x3f, 0x2a, 0x3f, - 0x15, 0x15, 0x0, - 0x15, 0x15, 0x2a, - 0x15, 0x3f, 0x0, - 0x15, 0x3f, 0x2a, - 0x3f, 0x15, 0x0, - 0x3f, 0x15, 0x2a, - 0x3f, 0x3f, 0x0, - 0x3f, 0x3f, 0x2a, - 0x15, 0x15, 0x15, - 0x15, 0x15, 0x3f, - 0x15, 0x3f, 0x15, - 0x15, 0x3f, 0x3f, - 0x3f, 0x15, 0x15, - 0x3f, 0x15, 0x3f, - 0x3f, 0x3f, 0x15, - 0x3f, 0x3f, 0x3f, - 0x39, 0xc, 0x5, - 0x15, 0x2c, 0xf, - 0x26, 0x10, 0x3d, - 0x29, 0x29, 0x38, - 0x4, 0x1a, 0xe, - 0x2, 0x1e, 0x3a, - 0x3c, 0x25, 0x33, - 0x3c, 0xc, 0x2c, - 0x3f, 0x3, 0x2b, - 0x1c, 0x9, 0x13, - 0x25, 0x2a, 0x35, - 0x1e, 0xa, 0x38, - 0x24, 0x8, 0x3, - 0x3, 0xe, 0x36, - 0xc, 0x6, 0x2a, - 0x26, 0x3, 0x32, - 0x5, 0x2f, 0x33, - 0x3c, 0x35, 0x2f, - 0x2d, 0x26, 0x3e, - 0xd, 0xa, 0x10, - 0x25, 0x3c, 0x11, - 0xd, 0x4, 0x2e, - 0x5, 0x19, 0x3e, - 0xc, 0x13, 0x34, - 0x2b, 0x6, 0x24, - 0x4, 0x3, 0xd, - 0x2f, 0x3c, 0xc, - 0x2a, 0x37, 0x1f, - 0xf, 0x12, 0x38, - 0x38, 0xe, 0x2a, - 0x12, 0x2f, 0x19, - 0x29, 0x2e, 0x31, - 0x25, 0x13, 0x3e, - 0x33, 0x3e, 0x33, - 0x1d, 0x2c, 0x25, - 0x15, 0x15, 0x5, - 0x32, 0x25, 0x39, - 0x1a, 0x7, 0x1f, - 0x13, 0xe, 0x1d, - 0x36, 0x17, 0x34, - 0xf, 0x15, 0x23, - 0x2, 0x35, 0xd, - 0x15, 0x3f, 0xc, - 0x14, 0x2f, 0xf, - 0x19, 0x21, 0x3e, - 0x27, 0x11, 0x2f, - 0x38, 0x3f, 0x3c, - 0x36, 0x2d, 0x15, - 0x16, 0x17, 0x2, - 0x1, 0xa, 0x3d, - 0x1b, 0x11, 0x3f, - 0x21, 0x3c, 0xd, - 0x1a, 0x39, 0x3d, - 0x8, 0xe, 0xe, - 0x22, 0x21, 0x23, - 0x1e, 0x30, 0x5, - 0x1f, 0x22, 0x3d, - 0x1e, 0x2f, 0xa, - 0x0, 0x1c, 0xe, - 0x0, 0x1c, 0x15, - 0x0, 0x1c, 0x1c, - 0x0, 0x15, 0x1c, - 0x0, 0xe, 0x1c, - 0x0, 0x7, 0x1c, - 0xe, 0xe, 0x1c, - 0x11, 0xe, 0x1c, - 0x15, 0xe, 0x1c, - 0x18, 0xe, 0x1c, - 0x1c, 0xe, 0x1c, - 0x1c, 0xe, 0x18, - 0x1c, 0xe, 0x15, - 0x1c, 0xe, 0x11, - 0x1c, 0xe, 0xe, - 0x1c, 0x11, 0xe, - 0x1c, 0x15, 0xe, - 0x1c, 0x18, 0xe, - 0x1c, 0x1c, 0xe, - 0x18, 0x1c, 0xe, - 0x15, 0x1c, 0xe, - 0x11, 0x1c, 0xe, - 0xe, 0x1c, 0xe, - 0xe, 0x1c, 0x11, - 0xe, 0x1c, 0x15, - 0xe, 0x1c, 0x18, - 0xe, 0x1c, 0x1c, - 0xe, 0x18, 0x1c, - 0xe, 0x15, 0x1c, - 0xe, 0x11, 0x1c, - 0x14, 0x14, 0x1c, - 0x16, 0x14, 0x1c, - 0x18, 0x14, 0x1c, - 0x1a, 0x14, 0x1c, - 0x1c, 0x14, 0x1c, - 0x1c, 0x14, 0x1a, - 0x1c, 0x14, 0x18, - 0x1c, 0x14, 0x16, - 0x1c, 0x14, 0x14, - 0x1c, 0x16, 0x14, - 0x1c, 0x18, 0x14, - 0x1c, 0x1a, 0x14, - 0x1c, 0x1c, 0x14, - 0x1a, 0x1c, 0x14, - 0x18, 0x1c, 0x14, - 0x16, 0x1c, 0x14, - 0x14, 0x1c, 0x14, - 0x14, 0x1c, 0x16, - 0x14, 0x1c, 0x18, - 0x14, 0x1c, 0x1a, - 0x14, 0x1c, 0x1c, - 0x14, 0x1a, 0x1c, - 0x14, 0x18, 0x1c, - 0x14, 0x16, 0x1c, - 0x0, 0x0, 0x10, - 0x4, 0x0, 0x10, - 0x8, 0x0, 0x10, - 0xc, 0x0, 0x10, - 0x10, 0x0, 0x10, - 0x10, 0x0, 0xc, - 0x10, 0x0, 0x8, - 0x10, 0x0, 0x4, - 0x10, 0x0, 0x0, - 0x10, 0x4, 0x0, - 0x10, 0x8, 0x0, - 0x10, 0xc, 0x0, - 0x10, 0x10, 0x0, - 0xc, 0x10, 0x0, - 0x8, 0x10, 0x0, - 0x4, 0x10, 0x0, - 0x0, 0x10, 0x0, - 0x0, 0x10, 0x4, - 0x0, 0x10, 0x8, - 0x0, 0x10, 0xc, - 0x0, 0x10, 0x10, - 0x0, 0xc, 0x10, - 0x0, 0x8, 0x10, - 0x0, 0x4, 0x10, - 0x8, 0x8, 0x10, - 0xa, 0x8, 0x10, - 0xc, 0x8, 0x10, - 0xe, 0x8, 0x10, - 0x10, 0x8, 0x10, - 0x10, 0x8, 0xe, - 0x10, 0x8, 0xc, - 0x10, 0x8, 0xa, - 0x10, 0x8, 0x8, - 0x10, 0xa, 0x8, - 0x10, 0xc, 0x8, - 0x10, 0xe, 0x8, - 0x10, 0x10, 0x8, - 0xe, 0x10, 0x8, - 0xc, 0x10, 0x8, - 0xa, 0x10, 0x8, - 0x8, 0x10, 0x8, - 0x8, 0x10, 0xa, - 0x8, 0x10, 0xc, - 0x8, 0x10, 0xe, - 0x8, 0x10, 0x10, - 0x8, 0xe, 0x10, - 0x8, 0xc, 0x10, - 0x8, 0xa, 0x10, - 0xb, 0xb, 0x10, - 0xc, 0xb, 0x10, - 0xd, 0xb, 0x10, - 0xf, 0xb, 0x10, - 0x10, 0xb, 0x10, - 0x10, 0xb, 0xf, - 0x10, 0xb, 0xd, - 0x10, 0xb, 0xc, - 0x10, 0xb, 0xb, - 0x10, 0xc, 0xb, - 0x10, 0xd, 0xb, - 0x10, 0xf, 0xb, - 0x10, 0x10, 0xb, - 0xf, 0x10, 0xb, - 0xd, 0x10, 0xb, - 0xc, 0x10, 0xb, - 0xb, 0x10, 0xb, - 0xb, 0x10, 0xc, - 0xb, 0x10, 0xd, - 0xb, 0x10, 0xf, - 0xb, 0x10, 0x10, - 0xb, 0xf, 0x10, - 0xb, 0xd, 0x10, - 0xb, 0xc, 0x10, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0 + /* red green blue */ + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x2a }, + { 0x0, 0x2a, 0x0 }, + { 0x0, 0x2a, 0x2a }, + { 0x2a, 0x0, 0x0 }, + { 0x2a, 0x0, 0x2a }, + { 0x2a, 0x2a, 0x0 }, + { 0x2a, 0x2a, 0x2a }, + { 0x0, 0x0, 0x15 }, + { 0x0, 0x0, 0x3f }, + { 0x0, 0x2a, 0x15 }, + { 0x0, 0x2a, 0x3f }, + { 0x2a, 0x0, 0x15 }, + { 0x2a, 0x0, 0x3f }, + { 0x2a, 0x2a, 0x15 }, + { 0x2a, 0x2a, 0x3f }, + { 0x0, 0x15, 0x0 }, + { 0x0, 0x15, 0x2a }, + { 0x0, 0x3f, 0x0 }, + { 0x0, 0x3f, 0x2a }, + { 0x2a, 0x15, 0x0 }, + { 0x2a, 0x15, 0x2a }, + { 0x2a, 0x3f, 0x0 }, + { 0x2a, 0x3f, 0x2a }, + { 0x0, 0x15, 0x15 }, + { 0x0, 0x15, 0x3f }, + { 0x0, 0x3f, 0x15 }, + { 0x0, 0x3f, 0x3f }, + { 0x2a, 0x15, 0x15 }, + { 0x2a, 0x15, 0x3f }, + { 0x2a, 0x3f, 0x15 }, + { 0x2a, 0x3f, 0x3f }, + { 0x15, 0x0, 0x0 }, + { 0x15, 0x0, 0x2a }, + { 0x15, 0x2a, 0x0 }, + { 0x15, 0x2a, 0x2a }, + { 0x3f, 0x0, 0x0 }, + { 0x3f, 0x0, 0x2a }, + { 0x3f, 0x2a, 0x0 }, + { 0x3f, 0x2a, 0x2a }, + { 0x15, 0x0, 0x15 }, + { 0x15, 0x0, 0x3f }, + { 0x15, 0x2a, 0x15 }, + { 0x15, 0x2a, 0x3f }, + { 0x3f, 0x0, 0x15 }, + { 0x3f, 0x0, 0x3f }, + { 0x3f, 0x2a, 0x15 }, + { 0x3f, 0x2a, 0x3f }, + { 0x15, 0x15, 0x0 }, + { 0x15, 0x15, 0x2a }, + { 0x15, 0x3f, 0x0 }, + { 0x15, 0x3f, 0x2a }, + { 0x3f, 0x15, 0x0 }, + { 0x3f, 0x15, 0x2a }, + { 0x3f, 0x3f, 0x0 }, + { 0x3f, 0x3f, 0x2a }, + { 0x15, 0x15, 0x15 }, + { 0x15, 0x15, 0x3f }, + { 0x15, 0x3f, 0x15 }, + { 0x15, 0x3f, 0x3f }, + { 0x3f, 0x15, 0x15 }, + { 0x3f, 0x15, 0x3f }, + { 0x3f, 0x3f, 0x15 }, + { 0x3f, 0x3f, 0x3f }, + { 0x39, 0xc, 0x5 }, + { 0x15, 0x2c, 0xf }, + { 0x26, 0x10, 0x3d }, + { 0x29, 0x29, 0x38 }, + { 0x4, 0x1a, 0xe }, + { 0x2, 0x1e, 0x3a }, + { 0x3c, 0x25, 0x33 }, + { 0x3c, 0xc, 0x2c }, + { 0x3f, 0x3, 0x2b }, + { 0x1c, 0x9, 0x13 }, + { 0x25, 0x2a, 0x35 }, + { 0x1e, 0xa, 0x38 }, + { 0x24, 0x8, 0x3 }, + { 0x3, 0xe, 0x36 }, + { 0xc, 0x6, 0x2a }, + { 0x26, 0x3, 0x32 }, + { 0x5, 0x2f, 0x33 }, + { 0x3c, 0x35, 0x2f }, + { 0x2d, 0x26, 0x3e }, + { 0xd, 0xa, 0x10 }, + { 0x25, 0x3c, 0x11 }, + { 0xd, 0x4, 0x2e }, + { 0x5, 0x19, 0x3e }, + { 0xc, 0x13, 0x34 }, + { 0x2b, 0x6, 0x24 }, + { 0x4, 0x3, 0xd }, + { 0x2f, 0x3c, 0xc }, + { 0x2a, 0x37, 0x1f }, + { 0xf, 0x12, 0x38 }, + { 0x38, 0xe, 0x2a }, + { 0x12, 0x2f, 0x19 }, + { 0x29, 0x2e, 0x31 }, + { 0x25, 0x13, 0x3e }, + { 0x33, 0x3e, 0x33 }, + { 0x1d, 0x2c, 0x25 }, + { 0x15, 0x15, 0x5 }, + { 0x32, 0x25, 0x39 }, + { 0x1a, 0x7, 0x1f }, + { 0x13, 0xe, 0x1d }, + { 0x36, 0x17, 0x34 }, + { 0xf, 0x15, 0x23 }, + { 0x2, 0x35, 0xd }, + { 0x15, 0x3f, 0xc }, + { 0x14, 0x2f, 0xf }, + { 0x19, 0x21, 0x3e }, + { 0x27, 0x11, 0x2f }, + { 0x38, 0x3f, 0x3c }, + { 0x36, 0x2d, 0x15 }, + { 0x16, 0x17, 0x2 }, + { 0x1, 0xa, 0x3d }, + { 0x1b, 0x11, 0x3f }, + { 0x21, 0x3c, 0xd }, + { 0x1a, 0x39, 0x3d }, + { 0x8, 0xe, 0xe }, + { 0x22, 0x21, 0x23 }, + { 0x1e, 0x30, 0x5 }, + { 0x1f, 0x22, 0x3d }, + { 0x1e, 0x2f, 0xa }, + { 0x0, 0x1c, 0xe }, + { 0x0, 0x1c, 0x15 }, + { 0x0, 0x1c, 0x1c }, + { 0x0, 0x15, 0x1c }, + { 0x0, 0xe, 0x1c }, + { 0x0, 0x7, 0x1c }, + { 0xe, 0xe, 0x1c }, + { 0x11, 0xe, 0x1c }, + { 0x15, 0xe, 0x1c }, + { 0x18, 0xe, 0x1c }, + { 0x1c, 0xe, 0x1c }, + { 0x1c, 0xe, 0x18 }, + { 0x1c, 0xe, 0x15 }, + { 0x1c, 0xe, 0x11 }, + { 0x1c, 0xe, 0xe }, + { 0x1c, 0x11, 0xe }, + { 0x1c, 0x15, 0xe }, + { 0x1c, 0x18, 0xe }, + { 0x1c, 0x1c, 0xe }, + { 0x18, 0x1c, 0xe }, + { 0x15, 0x1c, 0xe }, + { 0x11, 0x1c, 0xe }, + { 0xe, 0x1c, 0xe }, + { 0xe, 0x1c, 0x11 }, + { 0xe, 0x1c, 0x15 }, + { 0xe, 0x1c, 0x18 }, + { 0xe, 0x1c, 0x1c }, + { 0xe, 0x18, 0x1c }, + { 0xe, 0x15, 0x1c }, + { 0xe, 0x11, 0x1c }, + { 0x14, 0x14, 0x1c }, + { 0x16, 0x14, 0x1c }, + { 0x18, 0x14, 0x1c }, + { 0x1a, 0x14, 0x1c }, + { 0x1c, 0x14, 0x1c }, + { 0x1c, 0x14, 0x1a }, + { 0x1c, 0x14, 0x18 }, + { 0x1c, 0x14, 0x16 }, + { 0x1c, 0x14, 0x14 }, + { 0x1c, 0x16, 0x14 }, + { 0x1c, 0x18, 0x14 }, + { 0x1c, 0x1a, 0x14 }, + { 0x1c, 0x1c, 0x14 }, + { 0x1a, 0x1c, 0x14 }, + { 0x18, 0x1c, 0x14 }, + { 0x16, 0x1c, 0x14 }, + { 0x14, 0x1c, 0x14 }, + { 0x14, 0x1c, 0x16 }, + { 0x14, 0x1c, 0x18 }, + { 0x14, 0x1c, 0x1a }, + { 0x14, 0x1c, 0x1c }, + { 0x14, 0x1a, 0x1c }, + { 0x14, 0x18, 0x1c }, + { 0x14, 0x16, 0x1c }, + { 0x0, 0x0, 0x10 }, + { 0x4, 0x0, 0x10 }, + { 0x8, 0x0, 0x10 }, + { 0xc, 0x0, 0x10 }, + { 0x10, 0x0, 0x10 }, + { 0x10, 0x0, 0xc }, + { 0x10, 0x0, 0x8 }, + { 0x10, 0x0, 0x4 }, + { 0x10, 0x0, 0x0 }, + { 0x10, 0x4, 0x0 }, + { 0x10, 0x8, 0x0 }, + { 0x10, 0xc, 0x0 }, + { 0x10, 0x10, 0x0 }, + { 0xc, 0x10, 0x0 }, + { 0x8, 0x10, 0x0 }, + { 0x4, 0x10, 0x0 }, + { 0x0, 0x10, 0x0 }, + { 0x0, 0x10, 0x4 }, + { 0x0, 0x10, 0x8 }, + { 0x0, 0x10, 0xc }, + { 0x0, 0x10, 0x10 }, + { 0x0, 0xc, 0x10 }, + { 0x0, 0x8, 0x10 }, + { 0x0, 0x4, 0x10 }, + { 0x8, 0x8, 0x10 }, + { 0xa, 0x8, 0x10 }, + { 0xc, 0x8, 0x10 }, + { 0xe, 0x8, 0x10 }, + { 0x10, 0x8, 0x10 }, + { 0x10, 0x8, 0xe }, + { 0x10, 0x8, 0xc }, + { 0x10, 0x8, 0xa }, + { 0x10, 0x8, 0x8 }, + { 0x10, 0xa, 0x8 }, + { 0x10, 0xc, 0x8 }, + { 0x10, 0xe, 0x8 }, + { 0x10, 0x10, 0x8 }, + { 0xe, 0x10, 0x8 }, + { 0xc, 0x10, 0x8 }, + { 0xa, 0x10, 0x8 }, + { 0x8, 0x10, 0x8 }, + { 0x8, 0x10, 0xa }, + { 0x8, 0x10, 0xc }, + { 0x8, 0x10, 0xe }, + { 0x8, 0x10, 0x10 }, + { 0x8, 0xe, 0x10 }, + { 0x8, 0xc, 0x10 }, + { 0x8, 0xa, 0x10 }, + { 0xb, 0xb, 0x10 }, + { 0xc, 0xb, 0x10 }, + { 0xd, 0xb, 0x10 }, + { 0xf, 0xb, 0x10 }, + { 0x10, 0xb, 0x10 }, + { 0x10, 0xb, 0xf }, + { 0x10, 0xb, 0xd }, + { 0x10, 0xb, 0xc }, + { 0x10, 0xb, 0xb }, + { 0x10, 0xc, 0xb }, + { 0x10, 0xd, 0xb }, + { 0x10, 0xf, 0xb }, + { 0x10, 0x10, 0xb }, + { 0xf, 0x10, 0xb }, + { 0xd, 0x10, 0xb }, + { 0xc, 0x10, 0xb }, + { 0xb, 0x10, 0xb }, + { 0xb, 0x10, 0xc }, + { 0xb, 0x10, 0xd }, + { 0xb, 0x10, 0xf }, + { 0xb, 0x10, 0x10 }, + { 0xb, 0xf, 0x10 }, + { 0xb, 0xd, 0x10 }, + { 0xb, 0xc, 0x10 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x0 } }; unsigned char AC[21] = { @@ -721,7 +719,7 @@ } void -clearVideoMemory() +clearVideoMemory(void) { int i, j; for (i = 0; i < lines; i++) { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.4.9/linux/arch/ppc/config.in Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/config.in Tue Aug 28 07:11:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.config.in 1.34 07/08/01 11:39:11 trini +# BK Id: SCCS/s.config.in 1.40 08/24/01 20:31:47 paulus # # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. @@ -26,6 +26,7 @@ mainmenu_option next_comment comment 'Platform support' define_bool CONFIG_PPC y +define_bool CONFIG_PPC32 y choice 'Processor Type' \ "6xx/7xx/74xx/8260 CONFIG_6xx \ 4xx CONFIG_4xx \ @@ -42,6 +43,11 @@ define_bool CONFIG_ALL_PPC y fi +if [ "$CONFIG_6xx" = "y" -o "$CONFIG_POWER3" = "y" -o \ + "$CONFIG_POWER4" = "y" ]; then + define_bool CONFIG_PPC_STD_MMU y +fi + if [ "$CONFIG_8260" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y bool 'Support for EST8260' CONFIG_EST8260 @@ -93,7 +99,8 @@ bool 'Workarounds for PPC601 bugs' CONFIG_PPC601_SYNC_FIX fi -if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then +if [ "$CONFIG_POWER3" = "n" -a "$CONFIG_POWER4" = "n" -a \ + "$CONFIG_6xx" = "n" ]; then define_bool CONFIG_ALL_PPC n fi @@ -104,6 +111,11 @@ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then bool 'AltiVec Support' CONFIG_ALTIVEC + bool 'Thermal Management Support' CONFIG_TAU + if [ "$CONFIG_TAU" = "y" ]; then + bool ' Interrupt driven TAU driver (DANGEROUS)' CONFIG_TAU_INT + bool ' Average high and low temp' CONFIG_TAU_AVERAGE + fi fi if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/IVMS8_defconfig linux/arch/ppc/configs/IVMS8_defconfig --- v2.4.9/linux/arch/ppc/configs/IVMS8_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/IVMS8_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/SM850_defconfig linux/arch/ppc/configs/SM850_defconfig --- v2.4.9/linux/arch/ppc/configs/SM850_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/SM850_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/SPD823TS_defconfig linux/arch/ppc/configs/SPD823TS_defconfig --- v2.4.9/linux/arch/ppc/configs/SPD823TS_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/SPD823TS_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/TQM823L_defconfig linux/arch/ppc/configs/TQM823L_defconfig --- v2.4.9/linux/arch/ppc/configs/TQM823L_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/TQM823L_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/TQM850L_defconfig linux/arch/ppc/configs/TQM850L_defconfig --- v2.4.9/linux/arch/ppc/configs/TQM850L_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/TQM850L_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/TQM860L_defconfig linux/arch/ppc/configs/TQM860L_defconfig --- v2.4.9/linux/arch/ppc/configs/TQM860L_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/TQM860L_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/apus_defconfig linux/arch/ppc/configs/apus_defconfig --- v2.4.9/linux/arch/ppc/configs/apus_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/apus_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,21 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y # CONFIG_ALL_PPC is not set CONFIG_APUS=y # CONFIG_GEMINI is not set # CONFIG_PPC601_SYNC_FIX is not set # CONFIG_SMP is not set # CONFIG_ALTIVEC is not set +# CONFIG_TAU is not set # # General setup @@ -746,8 +749,10 @@ CONFIG_SOUND=y CONFIG_DMASOUND_PAULA=m CONFIG_DMASOUND=m +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -756,6 +761,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/bseip_defconfig linux/arch/ppc/configs/bseip_defconfig --- v2.4.9/linux/arch/ppc/configs/bseip_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/bseip_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig --- v2.4.9/linux/arch/ppc/configs/common_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/common_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,23 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_GEMINI is not set CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # # General setup @@ -228,6 +233,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y @@ -237,8 +243,8 @@ # CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -249,7 +255,8 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set @@ -769,8 +776,10 @@ CONFIG_SOUND=m CONFIG_DMASOUND_AWACS=m CONFIG_DMASOUND=m +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -779,6 +788,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/est8260_defconfig linux/arch/ppc/configs/est8260_defconfig --- v2.4.9/linux/arch/ppc/configs/est8260_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/est8260_defconfig Tue Aug 28 06:58:33 2001 @@ -19,16 +19,17 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set CONFIG_8260=y +CONFIG_PPC_STD_MMU=y CONFIG_SERIAL_CONSOLE=y CONFIG_EST8260=y CONFIG_PPC601_SYNC_FIX=y -# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set # diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig --- v2.4.9/linux/arch/ppc/configs/gemini_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/gemini_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,23 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set CONFIG_GEMINI=y # CONFIG_PPC601_SYNC_FIX is not set # CONFIG_SMP is not set CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # # General setup diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/ibmchrp_defconfig linux/arch/ppc/configs/ibmchrp_defconfig --- v2.4.9/linux/arch/ppc/configs/ibmchrp_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/ibmchrp_defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,21 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_GEMINI is not set # CONFIG_PPC601_SYNC_FIX is not set # CONFIG_SMP is not set # CONFIG_ALTIVEC is not set +# CONFIG_TAU is not set # # General setup diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/mbx_defconfig linux/arch/ppc/configs/mbx_defconfig --- v2.4.9/linux/arch/ppc/configs/mbx_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/mbx_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig --- v2.4.9/linux/arch/ppc/configs/oak_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/oak_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set CONFIG_4xx=y # CONFIG_POWER3 is not set @@ -29,6 +30,7 @@ CONFIG_OAK=y # CONFIG_WALNUT is not set CONFIG_PPC601_SYNC_FIX=y +# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set # CONFIG_MATH_EMULATION is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/power3_defconfig linux/arch/ppc/configs/power3_defconfig --- v2.4.9/linux/arch/ppc/configs/power3_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/power3_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set CONFIG_POWER3=y @@ -28,6 +29,7 @@ # CONFIG_8xx is not set CONFIG_PPC64BRIDGE=y CONFIG_ALL_PPC=y +CONFIG_PPC_STD_MMU=y CONFIG_SMP=y # CONFIG_IRQ_ALL_CPUS is not set @@ -640,8 +642,10 @@ # CONFIG_SOUND=y # CONFIG_DMASOUND_AWACS is not set +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -650,6 +654,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/rpxcllf_defconfig linux/arch/ppc/configs/rpxcllf_defconfig --- v2.4.9/linux/arch/ppc/configs/rpxcllf_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/rpxcllf_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/rpxlite_defconfig linux/arch/ppc/configs/rpxlite_defconfig --- v2.4.9/linux/arch/ppc/configs/rpxlite_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/rpxlite_defconfig Tue Aug 28 06:58:33 2001 @@ -19,6 +19,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_4xx is not set # CONFIG_POWER3 is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig --- v2.4.9/linux/arch/ppc/configs/walnut_defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/configs/walnut_defconfig Tue Aug 28 06:58:33 2001 @@ -21,6 +21,7 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y # CONFIG_6xx is not set CONFIG_4xx=y # CONFIG_POWER3 is not set @@ -29,6 +30,7 @@ # CONFIG_OAK is not set CONFIG_WALNUT=y CONFIG_PPC601_SYNC_FIX=y +# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set # CONFIG_MATH_EMULATION is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.4.9/linux/arch/ppc/defconfig Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/defconfig Tue Aug 28 06:58:33 2001 @@ -21,18 +21,23 @@ # Platform support # CONFIG_PPC=y +CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_8260 is not set +CONFIG_PPC_STD_MMU=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_GEMINI is not set CONFIG_PPC601_SYNC_FIX=y # CONFIG_SMP is not set CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # # General setup @@ -228,6 +233,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y @@ -237,8 +243,8 @@ # CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -249,7 +255,8 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set @@ -769,8 +776,10 @@ CONFIG_SOUND=m CONFIG_DMASOUND_AWACS=m CONFIG_DMASOUND=m +# CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set # CONFIG_SOUND_ES1370 is not set @@ -779,6 +788,7 @@ # CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_MAESTRO3 is not set # CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set # CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.4.9/linux/arch/ppc/kernel/Makefile Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.24 07/10/01 12:12:22 trini +# BK Id: SCCS/s.Makefile 1.32 08/24/01 20:07:37 paulus # # # Makefile for the linux kernel. @@ -29,12 +29,13 @@ O_TARGET := kernel.o -export-objs := ppc_ksyms.o prep_setup.o +export-objs := ppc_ksyms.o prep_setup.o time.o obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o \ ppc_htab.o semaphore.o syscalls.o \ - align.o setup.o + align.o setup.o cputable.o +obj-$(CONFIG_6xx) += l2cr.o obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_POWER4) += xics.o obj-$(CONFIG_PCI) += pci.o pci-dma.o @@ -43,6 +44,7 @@ obj-$(CONFIG_4xx) += ppc4xx_pic.o obj-$(CONFIG_OAK) += oak_setup.o obj-$(CONFIG_WALNUT) += walnut_setup.o +obj-$(CONFIG_TAU) += temp.o ifeq ($(CONFIG_WALNUT),y) obj-$(CONFIG_PCI) += galaxy_pci.o endif @@ -71,12 +73,17 @@ obj-$(CONFIG_GEMINI) += gemini_prom.o gemini_pci.o gemini_setup.o \ open_pic.o obj-$(CONFIG_8260) += m8260_setup.o ppc8260_pic.o +obj-$(CONFIG_BOOTX_TEXT) += btext.o +ifeq ($(CONFIG_SMP),y) +obj-$(CONFIG_ALL_PPC) += pmac_smp.o chrp_smp.o +endif include $(TOPDIR)/Rules.make entry.o: entry.S ppc_defs.h misc.o: misc.S ppc_defs.h +l2cr.o: l2cr.S ppc_defs.h head.o: head.S ppc_defs.h head_4xx.o: head_4xx.S ppc_defs.h head_8xx.o: head_8xx.S ppc_defs.h diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c --- v2.4.9/linux/arch/ppc/kernel/apus_setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/apus_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.apus_setup.c 1.14 07/06/01 09:19:28 trini + * BK Id: SCCS/s.apus_setup.c 1.18 08/20/01 15:25:16 paulus */ /* * linux/arch/ppc/kernel/apus_setup.c @@ -611,32 +611,8 @@ /* * IDE stuff. */ -void ide_insw(ide_ioreg_t port, void *buf, int ns); -void ide_outsw(ide_ioreg_t port, void *buf, int ns); -void -apus_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - ide_insw(port, buf, ns); -} - -void -apus_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - ide_outsw(port, buf, ns); -} - -int -apus_ide_default_irq(ide_ioreg_t base) -{ - return 0; -} - -ide_ioreg_t -apus_ide_default_io_base(int index) -{ - return 0; -} +#if 0 /* no longer used -- paulus */ void apus_ide_fix_driveid(struct hd_driveid *id) { @@ -682,6 +658,7 @@ } } } +#endif /* 0 */ __init void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, @@ -1039,6 +1016,15 @@ return total; } +static void __init +apus_map_io(void) +{ + /* Map PPC exception vectors. */ + io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL); + /* Map chip and ZorroII memory */ + io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO); +} + __init void apus_init_IRQ(void) { @@ -1061,8 +1047,8 @@ } __init -void apus_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { extern int parse_bootinfo(const struct bi_record *); extern char _end[]; @@ -1113,6 +1099,7 @@ ppc_md.calibrate_decr = apus_calibrate_decr; ppc_md.find_end_of_memory = apus_find_end_of_memory; + ppc_md.setup_io_mappings = apus_map_io; ppc_md.nvram_read_val = NULL; ppc_md.nvram_write_val = NULL; @@ -1130,14 +1117,7 @@ #endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = apus_ide_insw; - ppc_ide_md.outsw = apus_ide_outsw; - ppc_ide_md.default_irq = apus_ide_default_irq; - ppc_ide_md.default_io_base = apus_ide_default_io_base; - ppc_ide_md.fix_driveid = apus_ide_fix_driveid; ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; #endif } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/btext.c linux/arch/ppc/kernel/btext.c --- v2.4.9/linux/arch/ppc/kernel/btext.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/btext.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,868 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Procedures for drawing on the screen early on in the boot process. + * + * Benjamin Herrenschmidt + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NO_SCROLL + +#ifndef NO_SCROLL +static void scrollscreen(void); +#endif + +static void draw_byte(unsigned char c, long locX, long locY); +static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb); +static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb); +static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb); + +static int g_loc_X; +static int g_loc_Y; +static int g_max_loc_X; +static int g_max_loc_Y; + +unsigned long disp_BAT[2] __initdata = {0, 0}; + +#define cmapsz (16*256) + +static unsigned char vga_font[cmapsz]; + +int boot_text_mapped = 1; + +boot_infos_t *disp_bi; +boot_infos_t fake_bi; + +extern char *klimit; + +/* + * Powermac can use btext_* after boot for xmon, + * chrp only uses it during early boot. + */ +#ifdef CONFIG_XMON +#define BTEXT __pmac +#define BTDATA __pmacdata +#else +#define BTEXT __init +#define BTDATA __initdata +#endif /* CONFIG_XMON */ + +/* + * This is called only when we are booted via BootX. + */ +void __init +btext_init(boot_infos_t *bi) +{ + unsigned long offset = reloc_offset(); + + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; + RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; + RELOC(disp_bi) = PTRUNRELOC(bi); +} + +void __init +btext_welcome(boot_infos_t* bi) +{ + unsigned long offset = reloc_offset(); + unsigned long flags; + unsigned long pvr; + + btext_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); + btext_drawstring(RELOC("\nlinked at : 0x")); + btext_drawhex(KERNELBASE); + btext_drawstring(RELOC("\nframe buffer at : 0x")); + btext_drawhex((unsigned long)bi->dispDeviceBase); + btext_drawstring(RELOC(" (phys), 0x")); + btext_drawhex((unsigned long)bi->logicalDisplayBase); + btext_drawstring(RELOC(" (log)")); + btext_drawstring(RELOC("\nklimit : 0x")); + btext_drawhex((unsigned long)RELOC(klimit)); + btext_drawstring(RELOC("\nMSR : 0x")); + __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); + btext_drawhex(flags); + __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); + pvr >>= 16; + if (pvr > 1) { + btext_drawstring(RELOC("\nHID0 : 0x")); + __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); + btext_drawhex(flags); + } + if (pvr == 8 || pvr == 12 || pvr == 0x800c) { + btext_drawstring(RELOC("\nICTC : 0x")); + __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); + btext_drawhex(flags); + } + btext_drawstring(RELOC("\n\n")); +} + +/* Calc BAT values for mapping the display and store them + * in disp_BAT. Those values are then used from head.S to map + * the display during identify_machine() and MMU_Init() + * + * The display is mapped to virtual address 0xD0000000, rather + * than 1:1, because some some CHRP machines put the frame buffer + * in the region starting at 0xC0000000 (KERNELBASE). + * This mapping is temporary and will disappear as soon as the + * setup done by MMU_Init() is applied. + * + * For now, we align the BAT and then map 8Mb on 601 and 16Mb + * on other PPCs. This may cause trouble if the framebuffer + * is really badly aligned, but I didn't encounter this case + * yet. + */ +void __init +btext_prepare_BAT(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long addr = (unsigned long)bi->dispDeviceBase; + unsigned long vaddr = KERNELBASE + 0x10000000; + unsigned long lowbits; + + if (!RELOC(disp_bi)) { + RELOC(boot_text_mapped) = 0; + return; + } + if (PVR_VER(mfspr(PVR)) != 1) { + /* 603, 604, G3, G4, ... */ + lowbits = addr & ~0xFF000000UL; + addr &= 0xFF000000UL; + RELOC(disp_BAT[0]) = vaddr | (BL_16M<<2) | 2; + RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); + } else { + /* 601 */ + lowbits = addr & ~0xFF800000UL; + addr &= 0xFF800000UL; + RELOC(disp_BAT[0]) = vaddr | (_PAGE_NO_CACHE | PP_RWXX) | 4; + RELOC(disp_BAT[1]) = addr | BL_8M | 0x40; + } + bi->logicalDisplayBase = (void *) (vaddr + lowbits); +} + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +void __init +btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi; + + RELOC(disp_bi) = &fake_bi; + bi = PTRRELOC((&fake_bi)); + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = width / 8; + RELOC(g_max_loc_Y) = height / 16; + bi->logicalDisplayBase = (unsigned char *)address; + bi->dispDeviceBase = (unsigned char *)address; + bi->dispDeviceRowBytes = pitch; + bi->dispDeviceDepth = depth; + bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; +} + +/* Here's a small text engine to use during early boot + * or for debugging purposes + * + * todo: + * + * - build some kind of vgacon with it to enable early printk + * - move to a separate file + * - add a few video driver hooks to keep in sync with display + * changes. + */ + +void __openfirmware +map_boot_text(void) +{ + unsigned long base, offset, size; + if (disp_bi == 0) + return; + base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) disp_bi->dispDeviceBase) - base; + size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset + + disp_bi->dispDeviceRect[0]; + disp_bi->logicalDisplayBase = ioremap(base, size); + if (disp_bi->logicalDisplayBase == 0) + return; + disp_bi->logicalDisplayBase += offset; + boot_text_mapped = 1; +} + +/* Calc the base address of a given point (x,y) */ +static unsigned char * BTEXT +calc_base(boot_infos_t *bi, int x, int y) +{ + unsigned char *base; + + base = bi->logicalDisplayBase; + if (base == 0) + base = bi->dispDeviceBase; + base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); + base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; + return base; +} + +/* Adjust the display to a new resolution */ +void +btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch) +{ + if (disp_bi == 0) + return; + /* check it's the same frame buffer (within 64MB) */ + if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) { + return; + } + + disp_bi->dispDeviceBase = (__u8 *) phys; + disp_bi->dispDeviceRect[0] = 0; + disp_bi->dispDeviceRect[1] = 0; + disp_bi->dispDeviceRect[2] = width; + disp_bi->dispDeviceRect[3] = height; + disp_bi->dispDeviceDepth = depth; + disp_bi->dispDeviceRowBytes = pitch; + if (boot_text_mapped) { + iounmap(disp_bi->logicalDisplayBase); + boot_text_mapped = 0; + } + map_boot_text(); + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; +} + +void BTEXT btext_clearscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j; --j) + *(ptr++) = 0; + base += (bi->dispDeviceRowBytes >> 2); + } +} + +__inline__ void dcbst(const void* addr) +{ + __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr)); +} + +void BTEXT btext_flushscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j>0; j-=8) { + dcbst(ptr); + ptr += 8; + } + base += (bi->dispDeviceRowBytes >> 2); + } +} + +#ifndef NO_SCROLL +static BTEXT void +scrollscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long *src = (unsigned long *)calc_base(bi,0,16); + unsigned long *dst = (unsigned long *)calc_base(bi,0,0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 2; + int i,j; + +#ifdef CONFIG_ADB_PMU + pmu_suspend(); /* PMU will not shut us down ! */ +#endif + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) + { + unsigned long *src_ptr = src; + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = *(src_ptr++); + src += (bi->dispDeviceRowBytes >> 2); + dst += (bi->dispDeviceRowBytes >> 2); + } + for (i=0; i<16; i++) + { + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = 0; + dst += (bi->dispDeviceRowBytes >> 2); + } +#ifdef CONFIG_ADB_PMU + pmu_resume(); /* PMU will not shut us down ! */ +#endif +} +#endif /* ndef NO_SCROLL */ + +void BTEXT btext_drawchar(char c) +{ + unsigned long offset = reloc_offset(); + int cline = 0, x; + + if (!RELOC(boot_text_mapped)) + return; + + switch (c) { + case '\b': + if (RELOC(g_loc_X) > 0) + --RELOC(g_loc_X); + break; + case '\t': + RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; + break; + case '\r': + RELOC(g_loc_X) = 0; + break; + case '\n': + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + break; + default: + draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); + } + if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + } +#ifndef NO_SCROLL + while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { + scrollscreen(); + RELOC(g_loc_Y)--; + } +#else + /* wrap around from bottom to top of screen so we don't + waste time scrolling each line. -- paulus. */ + if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) + RELOC(g_loc_Y) = 0; + if (cline) { + for (x = 0; x < RELOC(g_max_loc_X); ++x) + draw_byte(' ', x, RELOC(g_loc_Y)); + } +#endif +} + +void BTEXT +btext_drawstring(const char *c) +{ + unsigned long offset = reloc_offset(); + + if (!RELOC(boot_text_mapped)) + return; + while (*c) + btext_drawchar(*c++); +} + +void BTEXT +btext_drawhex(unsigned long v) +{ + static char hex_table[] = "0123456789abcdef"; + unsigned long offset = reloc_offset(); + + if (!RELOC(boot_text_mapped)) + return; + btext_drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]); + btext_drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]); + btext_drawchar(' '); +} + +static void BTEXT +draw_byte(unsigned char c, long locX, long locY) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned char *base = calc_base(bi, locX << 3, locY << 4); + unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16]; + int rb = bi->dispDeviceRowBytes; + + switch(bi->dispDeviceDepth) { + case 32: + draw_byte_32(font, (unsigned long *)base, rb); + break; + case 16: + draw_byte_16(font, (unsigned long *)base, rb); + break; + case 8: + draw_byte_8(font, (unsigned long *)base, rb); + break; + } +} + +static unsigned long expand_bits_8[16] BTDATA = { + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +static unsigned long expand_bits_16[4] BTDATA = { + 0x00000000, + 0x0000ffff, + 0xffff0000, + 0xffffffff +}; + + +static void BTEXT +draw_byte_32(unsigned char *font, unsigned long *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (-(bits >> 7) & fg) ^ bg; + base[1] = (-((bits >> 6) & 1) & fg) ^ bg; + base[2] = (-((bits >> 5) & 1) & fg) ^ bg; + base[3] = (-((bits >> 4) & 1) & fg) ^ bg; + base[4] = (-((bits >> 3) & 1) & fg) ^ bg; + base[5] = (-((bits >> 2) & 1) & fg) ^ bg; + base[6] = (-((bits >> 1) & 1) & fg) ^ bg; + base[7] = (-(bits & 1) & fg) ^ bg; + base = (unsigned long *) ((char *)base + rb); + } +} + +static void BTEXT +draw_byte_16(unsigned char *font, unsigned long *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned long *eb = RELOC(expand_bits_16); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 6] & fg) ^ bg; + base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; + base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; + base[3] = (eb[bits & 3] & fg) ^ bg; + base = (unsigned long *) ((char *)base + rb); + } +} + +static void BTEXT +draw_byte_8(unsigned char *font, unsigned long *base, int rb) +{ + int l, bits; + int fg = 0x0F0F0F0FUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned long *eb = RELOC(expand_bits_8); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 4] & fg) ^ bg; + base[1] = (eb[bits & 0xf] & fg) ^ bg; + base = (unsigned long *) ((char *)base + rb); + } +} + +static unsigned char vga_font[cmapsz] BTDATA = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +}; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.4.9/linux/arch/ppc/kernel/chrp_setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/chrp_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.chrp_setup.c 1.22 07/18/01 22:56:39 paulus + * BK Id: SCCS/s.chrp_setup.c 1.32 08/20/01 22:58:32 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "local_irq.h" #include "i8259.h" @@ -68,7 +69,7 @@ void chrp_event_scan(void); void rtas_display_progress(char *, unsigned short); void rtas_indicator_progress(char *, unsigned short); -void bootx_text_progress(char *, unsigned short); +void btext_progress(char *, unsigned short); extern unsigned long pmac_find_end_of_memory(void); extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); @@ -77,16 +78,10 @@ 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 int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); -extern void mackbd_init_hw(void); -extern unsigned char mackbd_sysrq_xlate[128]; +extern void select_adb_keyboard(void); extern kdev_t boot_dev; @@ -94,9 +89,13 @@ extern unsigned long Hash_size, Hash_mask; extern int probingmem; extern unsigned long loops_per_jiffy; -extern int bootx_text_mapped; static int max_width; +#ifdef CONFIG_SMP +extern struct smp_ops_t chrp_smp_ops; +extern struct smp_ops_t xics_smp_ops; +#endif + static const char *gg2_memtypes[4] = { "FPM", "SDRAM", "EDO", "BEDO" }; @@ -248,9 +247,6 @@ chrp_find_bridges(); #ifndef CONFIG_PPC64BRIDGE - /* PCI bridge config space access area - - * appears to be not in devtree on longtrail. */ - ioremap(GG2_PCI_CONFIG_BASE, 0x80000); /* * Temporary fixes for PCI devices. * -- Geert @@ -259,7 +255,6 @@ #endif /* CONFIG_PPC64BRIDGE */ -#ifndef CONFIG_POWER4 /* Some IBM machines don't have the hydra -- Cort */ if (!OpenPIC_Addr) { struct device_node *root; @@ -276,7 +271,6 @@ OpenPIC_Addr = ioremap(opprop[n-1], 0x40000); } } -#endif /* * Fix the Super I/O configuration @@ -401,9 +395,6 @@ void __init chrp_init2(void) { -#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) - struct device_node *kbd; -#endif #ifdef CONFIG_NVRAM pmac_nvram_init(); #endif @@ -418,87 +409,35 @@ if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); -#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) +#if defined(CONFIG_VT) && (defined(CONFIG_ADB_KEYBOARD) || defined(CONFIG_INPUT)) /* see if there is a keyboard in the device tree with a parent of type "adb" */ - for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) - if (kbd->parent && kbd->parent->type - && strcmp(kbd->parent->type, "adb") == 0) - break; - if (kbd) { - ppc_md.kbd_setkeycode = mackbd_setkeycode; - ppc_md.kbd_getkeycode = mackbd_getkeycode; - ppc_md.kbd_translate = mackbd_translate; - ppc_md.kbd_unexpected_up = mackbd_unexpected_up; - ppc_md.kbd_leds = mackbd_leds; - ppc_md.kbd_init_hw = mackbd_init_hw; -#ifdef CONFIG_MAGIC_SYSRQ - ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; - SYSRQ_KEY = 0x69; -#endif /* CONFIG_MAGIC_SYSRQ */ + { + struct device_node *kbd; + + for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) { + if (kbd->parent && kbd->parent->type + && strcmp(kbd->parent->type, "adb") == 0) { + select_adb_keyboard(); + break; + } + } } -#endif /* CONFIG_VT && CONFIG_ADB_KEYBOARD */ +#endif /* CONFIG_VT && (CONFIG_ADB_KEYBOARD || CONFIG_INPUT) */ } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) /* * IDE stuff. */ -unsigned int chrp_ide_irq = 0; -int chrp_ide_ports_known = 0; -ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; -ide_ioreg_t chrp_idedma_regbase; - -void __chrp -chrp_ide_probe(void) -{ - struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); - - chrp_ide_ports_known = 1; - - if(pdev) { - chrp_ide_regbase[0]=pdev->resource[0].start; - chrp_ide_regbase[1]=pdev->resource[2].start; - chrp_idedma_regbase=pdev->resource[4].start; - chrp_ide_irq=pdev->irq; - } -} -void __chrp -chrp_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - ide_insw(port+_IO_BASE, buf, ns); -} - -void __chrp -chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - ide_outsw(port+_IO_BASE, buf, ns); -} - -int __chrp -chrp_ide_default_irq(ide_ioreg_t base) -{ - if (chrp_ide_ports_known == 0) - chrp_ide_probe(); - return chrp_ide_irq; -} - -ide_ioreg_t __chrp -chrp_ide_default_io_base(int index) -{ - if (chrp_ide_ports_known == 0) - chrp_ide_probe(); - return chrp_ide_regbase[index]; -} - -int __chrp +static int __chrp chrp_ide_check_region(ide_ioreg_t from, unsigned int extent) { return check_region(from, extent); } -void __chrp +static void __chrp chrp_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) @@ -506,14 +445,14 @@ request_region(from, extent, name); } -void __chrp +static void __chrp chrp_ide_release_region(ide_ioreg_t from, unsigned int extent) { release_region(from, extent); } -void __chrp +static void __chrp chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; @@ -523,20 +462,42 @@ hw->io_ports[i] = reg; reg += 1; } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; +} +#endif + +/* + * One of the main thing these mappings are needed for is so that + * xmon can get to the serial port early on. We probably should + * handle the machines with the mpc106 as well as the python (F50) + * and the GG2 (longtrail). Actually we should look in the device + * tree and do the right thing. + */ +static void __init +chrp_map_io(void) +{ + char *name; + + /* + * The code below tends to get removed, please don't take it out. + * The F50 needs this mapping and it you take it out I'll track you + * down and slap your hands. If it causes problems please email me. + * -- Cort + */ + name = get_property(find_path_device("/"), "name", NULL); + if (name && strncmp(name, "IBM-70", 6) == 0 + && strstr(name, "-F50")) { + io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); + io_block_mapping(0x90000000, 0x90000000, 0x10000000, _PAGE_IO); + return; } else { - hw->io_ports[IDE_CONTROL_OFFSET] = 0; + io_block_mapping(0xf8000000, 0xf8000000, 0x04000000, _PAGE_IO); } - if (irq != NULL) - hw->irq = chrp_ide_irq; } -#endif - void __init - chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { #ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ @@ -576,6 +537,7 @@ ppc_md.calibrate_decr = chrp_calibrate_decr; ppc_md.find_end_of_memory = pmac_find_end_of_memory; + ppc_md.setup_io_mappings = chrp_map_io; #ifdef CONFIG_VT /* these are adjusted in chrp_init2 if we have an ADB keyboard */ @@ -584,6 +546,7 @@ ppc_md.kbd_translate = pckbd_translate; ppc_md.kbd_unexpected_up = pckbd_unexpected_up; ppc_md.kbd_leds = pckbd_leds; + ppc_md.kbd_rate_fn = pckbd_rate; ppc_md.kbd_init_hw = pckbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; @@ -608,22 +571,23 @@ } } #ifdef CONFIG_BOOTX_TEXT - if (ppc_md.progress == NULL && bootx_text_mapped) - ppc_md.progress = bootx_text_progress; + if (ppc_md.progress == NULL && boot_text_mapped) + ppc_md.progress = btext_progress; #endif +#ifdef CONFIG_SMP +#ifndef CONFIG_POWER4 + ppc_md.smp_ops = &chrp_smp_ops; +#else + ppc_md.smp_ops = &xics_smp_ops; +#endif /* CONFIG_POWER4 */ +#endif /* CONFIG_SMP */ + #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = chrp_ide_insw; - ppc_ide_md.outsw = chrp_ide_outsw; - ppc_ide_md.default_irq = chrp_ide_default_irq; - ppc_ide_md.default_io_base = chrp_ide_default_io_base; ppc_ide_md.ide_check_region = chrp_ide_check_region; ppc_ide_md.ide_request_region = chrp_ide_request_region; ppc_ide_md.ide_release_region = chrp_ide_release_region; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; #endif /* @@ -668,7 +632,7 @@ #ifdef CONFIG_BOOTX_TEXT void -bootx_text_progress(char *s, unsigned short hex) +btext_progress(char *s, unsigned short hex) { prom_print(s); prom_print("\n"); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/chrp_smp.c linux/arch/ppc/kernel/chrp_smp.c --- v2.4.9/linux/arch/ppc/kernel/chrp_smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/chrp_smp.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,149 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Smp support for CHRP machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great + * deal of code from the sparc and intel versions. + * + * Copyright (C) 1999 Cort Dougan + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open_pic.h" + +extern unsigned long smp_chrp_cpu_nr; + +static int +smp_chrp_probe(void) +{ + if (smp_chrp_cpu_nr > 1) + openpic_request_IPIs(); + + return smp_chrp_cpu_nr; +} + +static void +smp_chrp_kick_cpu(int nr) +{ + *(unsigned long *)KERNELBASE = nr; + asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); +} + +static void +smp_chrp_setup_cpu(int cpu_nr) +{ + static atomic_t ready = ATOMIC_INIT(1); + static volatile int frozen = 0; + + if (cpu_nr == 0) { + /* wait for all the others */ + while (atomic_read(&ready) < smp_num_cpus) + barrier(); + atomic_set(&ready, 1); + /* freeze the timebase */ + call_rtas("freeze-time-base", 0, 1, NULL); + mb(); + frozen = 1; + /* XXX assumes this is not a 601 */ + set_tb(0, 0); + last_jiffy_stamp(0) = 0; + while (atomic_read(&ready) < smp_num_cpus) + barrier(); + /* thaw the timebase again */ + call_rtas("thaw-time-base", 0, 1, NULL); + mb(); + frozen = 0; + smp_tb_synchronized = 1; + } else { + atomic_inc(&ready); + while (!frozen) + barrier(); + set_tb(0, 0); + last_jiffy_stamp(0) = 0; + mb(); + atomic_inc(&ready); + while (frozen) + barrier(); + } + + if (OpenPIC_Addr) + do_openpic_setup_cpu(); +} + +#ifdef CONFIG_POWER4 +static void +smp_xics_message_pass(int target, int msg, unsigned long data, int wait) +{ + /* for now, only do reschedule messages + since we only have one IPI */ + if (msg != PPC_MSG_RESCHEDULE) + return; + for (i = 0; i < smp_num_cpus; ++i) { + if (target == MSG_ALL || target == i + || (target == MSG_ALL_BUT_SELF + && i != smp_processor_id())) + xics_cause_IPI(i); + } +} + +static int +smp_xics_probe(void) +{ + return smp_chrp_cpu_nr; +} + +static void +smp_xics_setup_cpu(int cpu_nr) +{ + if (cpu_nr > 0) + xics_setup_cpu(); +} +#endif /* CONFIG_POWER4 */ + +/* CHRP with openpic */ +struct smp_ops_t chrp_smp_ops = { + smp_openpic_message_pass, + smp_chrp_probe, + smp_chrp_kick_cpu, + smp_chrp_setup_cpu, +}; + +#ifdef CONFIG_POWER4 +/* CHRP with new XICS interrupt controller */ +struct smp_ops_t xics_smp_ops = { + smp_xics_message_pass, + smp_xics_probe, + smp_chrp_kick_cpu, + smp_xics_setup_cpu, +}; +#endif /* CONFIG_POWER4 */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/cputable.c linux/arch/ppc/kernel/cputable.c --- v2.4.9/linux/arch/ppc/kernel/cputable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/cputable.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,283 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * arch/ppc/kernel/cputable.c + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +struct cpu_spec* cur_cpu_spec[NR_CPUS]; + +extern void __setup_cpu_601(int cpu_nr); +extern void __setup_cpu_603(int cpu_nr); +extern void __setup_cpu_604(int cpu_nr); +extern void __setup_cpu_750(int cpu_nr); +extern void __setup_cpu_7400(int cpu_nr); +extern void __setup_cpu_7450(int cpu_nr); +extern void __setup_cpu_power3(int cpu_nr); +extern void __setup_cpu_power4(int cpu_nr); +extern void __setup_cpu_8xx(int cpu_nr); +extern void __setup_cpu_generic(int cpu_nr); + +#define CLASSIC_PPC (!defined(CONFIG_8xx) && \ + !defined(CONFIG_4xx) && !defined(CONFIG_POWER3) && \ + !defined(CONFIG_POWER4) && !defined(CONFIG_PPC_ISERIES)) + +/* This table only contains "desktop" CPUs, it need to be filled with embedded + * ones as well... + */ +#define COMMON_PPC (PPC_FEATURE_32 | PPC_FEATURE_HAS_FPU | \ + PPC_FEATURE_HAS_MMU) + +/* We only set the altivec features if the kernel was compiled with altivec + * support + */ +#ifdef CONFIG_ALTIVEC +#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC +#else +#define CPU_FTR_ALTIVEC_COMP 0 +#endif + +struct cpu_spec cpu_specs[] = { +#if CLASSIC_PPC + { /* 601 */ + 0xffff0000, 0x00010000, "601", + CPU_FTR_601 | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_601_INSTR | PPC_FEATURE_UNIFIED_CACHE, + 32, 32, + __setup_cpu_601 + }, + { /* 603 */ + 0xffff0000, 0x00030000, "603", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* 603e */ + 0xffff0000, 0x00060000, "603e", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* 603ev */ + 0xffff0000, 0x00070000, "603ev", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* 604 */ + 0xffff0000, 0x00040000, "604", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 604e */ + 0xfffff000, 0x00090000, "604e", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 604r */ + 0xffff0000, 0x00090000, "604r", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 604ev */ + 0xffff0000, 0x000a0000, "604ev", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | + CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_604 + }, + { /* 750 (0x4202, don't support TAU ?) */ + 0xffffffff, 0x00084202, "750", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, + { /* 750CX */ + 0xffffff00, 0x00082200, "750CX", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, + { /* 740/750 (L2CR bit need fixup for 740) */ + 0xffff0000, 0x00080000, "740/750", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, + { /* 7400 rev 1.1 ? (no TAU) */ + 0xffffffff, 0x000c1101, "7400 (1.1)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7400 + }, + { /* 7400 */ + 0xffff0000, 0x000c0000, "7400", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7400 + }, + { /* 7410 */ + 0xffff0000, 0x800c0000, "7410", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7400 + }, + { /* 7450 */ + 0xffff0000, 0x80000000, "7450", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450, + COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC, + 32, 32, + __setup_cpu_7450 + }, + { /* 82xx (8240, 8245, 8260 are all 603e cores) */ + 0xffff0000, 0x00810000, "82xx", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, + COMMON_PPC, + 32, 32, + __setup_cpu_603 + }, + { /* default match, we assume split I/D cache & TB (non-601)... */ + 0x00000000, 0x00000000, "(generic PPC)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC, + 32, 32, + __setup_cpu_generic + }, +#endif /* CLASSIC_PPC */ +#ifdef CONFIG_PPC64BRIDGE + { /* Power3 */ + 0xffff0000, 0x00400000, "Power3 (630)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, + { /* Power3+ */ + 0xffff0000, 0x00410000, "Power3 (630+)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, + { /* I-star */ + 0xffff0000, 0x00360000, "I-star", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, + { /* S-star */ + 0xffff0000, 0x00370000, "S-star", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power3 + }, +#endif /* CONFIG_PPC64BRIDGE */ +#ifdef CONFIG_POWER4 + { /* Power4 */ + 0xffff0000, 0x00350000, "Power4", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_PPC | PPC_FEATURE_64, + 128, 128, + __setup_cpu_power4 + }, +#endif /* CONFIG_POWER4 */ +#ifdef CONFIG_8xx + { /* 8xx */ + 0xffff0000, 0x00500000, "8xx", + /* CPU_FTR_CAN_DOZE is possible, if the 8xx code is there.... */ + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, __setup_cpu_8xx + }, +#endif /* CONFIG_8xx */ +#ifdef CONFIG_4xx + { /* 403GC */ + 0xffffff00, 0x00200200, "403GC", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, /*__setup_cpu_403 */ + }, + { /* 403GCX */ + 0xffffff00, 0x00201400, "403GCX", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, /*__setup_cpu_403 */ + }, + { /* 403G ?? */ + 0xffff0000, 0x00200000, "403G ??", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + 16, 16, + 0, /*__setup_cpu_403 */ + }, + { /* 405GP */ + 0xffff0000, 0x40110000, "405GP", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + 32, 32, + 0, /*__setup_cpu_405 */ + }, + { /* STB 03xxx */ + 0xffff0000, 0x40130000, "STB03xxx", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, + PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + 32, 32, + 0, /*__setup_cpu_405 */ + }, +#endif /* CONFIG_4xx */ +#if !CLASSIC_PPC + { /* default match */ + 0x00000000, 0x00000000, "(generic PPC)", + 0, + PPC_FEATURE_32, + 32, 32, + 0, + } +#endif /* !CLASSIC_PPC */ +}; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.4.9/linux/arch/ppc/kernel/entry.S Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/entry.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.entry.S 1.20 07/19/01 23:02:48 paulus + * BK Id: SCCS/s.entry.S 1.22 08/15/01 22:43:06 paulus */ /* * PowerPC version @@ -23,12 +23,14 @@ */ #include "ppc_asm.h" +#include +#include +#include +#include #include #include #include -#include -#include -#include +#include #undef SHOW_SYSCALLS #undef SHOW_SYSCALLS_TASK @@ -217,7 +219,9 @@ mfmsr r22 li r0,MSR_FP /* Disable floating-point */ #ifdef CONFIG_ALTIVEC - oris r0,r0,MSR_VEC@h +BEGIN_FTR_SECTION + oris r0,r0,MSR_VEC@h /* Disable altivec */ +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ andc r22,r22,r0 mtmsr r22 @@ -238,21 +242,6 @@ tophys(r0,r4) CLR_TOP32(r0) mtspr SPRG3,r0 /* Update current THREAD phys addr */ -#ifdef CONFIG_8xx - /* XXX it would be nice to find a SPRGx for this on 6xx,7xx too */ - lwz r9,PGDIR(r4) /* cache the page table root */ - tophys(r9,r9) /* convert to phys addr */ -#ifdef CONFIG_8xx_CPU6 - lis r6, cpu6_errata_word@h - ori r6, r6, cpu6_errata_word@l - li r5, 0x3980 - stw r5, 8(r6) - lwz r5, 8(r6) -#endif - mtspr M_TWB,r9 /* Update MMU base address */ - tlbia - sync -#endif /* CONFIG_8xx */ lwz r1,KSP(r4) /* Load new stack pointer */ /* save the old current 'last' for return value */ mr r3,r2 @@ -328,19 +317,16 @@ andi. r0,r0,MSR_PR beq+ 1f #ifdef CONFIG_ALTIVEC - mfpvr r8 /* check if we are on a G4 */ - srwi r8,r8,16 - cmpwi r8,PVR_7400@h - bne 2f +BEGIN_FTR_SECTION lwz r0,THREAD+THREAD_VRSAVE(r2) - mtspr SPRN_VRSAVE,r0 /* if so, restore VRSAVE reg */ -2: + mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */ +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ addi r0,r1,INT_FRAME_SIZE /* size of frame */ stw r0,THREAD+KSP(r2) /* save kernel stack pointer */ tophys(r8,r1) CLR_TOP32(r8) - mtspr SPRG2,r8 /* phys exception stack pointer */ + mtspr SPRG2,r8 /* phys exception stack pointer */ 1: lwz r3,_CTR(r1) lwz r0,_LINK(r1) @@ -348,15 +334,32 @@ mtlr r0 REST_4GPRS(3, r1) REST_2GPRS(7, r1) + + /* We have to "dummy" load from the context save area in case + * these instructions cause an MMU fault. If this happens + * after we load SRR0/SRR1, our return context is hosed. -- Dan + */ + lwz r0,GPR0(r1) + lwz r0,GPR2(r1) + lwz r0,GPR1(r1) + + /* We re-use r3,r4 here (the load above was to cause the MMU + * fault if necessary). Using r3,r4 removes the need to "dummy" + * load the CCR and NIP. Since we load them we may as well + * use them. + */ + lwz r3,_CCR(r1) + lwz r4,_NIP(r1) + lwz r0,_MSR(r1) FIX_SRR1(r0,r2) mtspr SRR1,r0 - lwz r2,_CCR(r1) - mtcrf 0xFF,r2 - lwz r2,_NIP(r1) - mtspr SRR0,r2 + mtcrf 0xFF,r3 + mtspr SRR0,r4 lwz r0,GPR0(r1) lwz r2,GPR2(r1) + lwz r3,GPR3(r1) + lwz r4,GPR4(r1) lwz r1,GPR1(r1) SYNC RFI diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c --- v2.4.9/linux/arch/ppc/kernel/feature.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/feature.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.feature.c 1.16 07/06/01 14:42:47 trini + * BK Id: SCCS/s.feature.c 1.19 08/19/01 22:23:04 paulus */ /* * arch/ppc/kernel/feature.c @@ -38,11 +38,15 @@ #define FREG(c,r) (&(((c)->reg)[(r)>>2])) /* Keylargo reg. access. */ -#define KL_FCR(r) (keylargo_base + ((r) >> 2)) -#define KL_IN(r) (in_le32(KL_FCR(r))) -#define KL_OUT(r,v) (out_le32(KL_FCR(r), (v))) -#define KL_BIS(r,v) (KL_OUT((r), KL_IN(r) | (v))) -#define KL_BIC(r,v) (KL_OUT((r), KL_IN(r) & ~(v))) +#define KL_FCR(r) (keylargo_base + ((r) >> 2)) +#define KL_IN(r) (in_le32(KL_FCR(r))) +#define KL_OUT(r,v) (out_le32(KL_FCR(r), (v))) +#define KL_BIS(r,v) (KL_OUT((r), KL_IN(r) | (v))) +#define KL_BIC(r,v) (KL_OUT((r), KL_IN(r) & ~(v))) +#define KL_GPIO_IN(r) (in_8(((volatile u8 *)keylargo_base)+(r))) +#define KL_GPIO_OUT(r,v) (out_8(((volatile u8 *)keylargo_base)+(r), (v))) +#define KL_LOCK() spin_lock_irqsave(&keylargo->lock, flags) +#define KL_UNLOCK() spin_unlock_irqrestore(&keylargo->lock, flags) /* Uni-N reg. access. Note that Uni-N regs are big endian */ #define UN_REG(r) (uninorth_base + ((r) >> 2)) @@ -259,15 +263,29 @@ static int uninorth_rev; static int keylargo_rev; static u32 board_features; -static u8 airport_pwr_regs[5]; static int airport_pwr_state; static struct device_node* airport_dev; +static struct device_node* uninorth_fw; +/* Feature bits for Apple motherboards */ #define FTR_NEED_OPENPIC_TWEAK 0x00000001 #define FTR_CAN_NAP 0x00000002 #define FTR_HAS_FW_POWER 0x00000004 #define FTR_CAN_SLEEP 0x00000008 +/* This table currently lacks most oldworld machines, but + * they currently don't need it so... + * + * Todo: The whole feature_xxx mecanism need to be redone + * some way to be able to handle the new kind of features + * exposed by core99. At this point, the main "tables" will + * probably be in this table, which will have to be filled with + * all known machines + */ +/* Warning: Don't change ordering of entries as some machines + * adverstise beeing compatible with several models. In those + * case, the "highest" has to be first + */ static struct board_features_t { char* compatible; u32 features; @@ -283,17 +301,21 @@ { "PowerMac3,1", FTR_NEED_OPENPIC_TWEAK }, /* Sawtooth (G4) */ { "PowerMac3,2", 0 }, /* G4/Dual G4 */ { "PowerMac3,3", FTR_NEED_OPENPIC_TWEAK }, /* G4/Dual G4 */ - { "PowerMac5,1", 0 }, /* Cube */ + { "PowerMac3,4", 0 }, /* QuickSilver G4 */ + { "PowerMac3,5", 0 }, /* QuickSilver G4 */ + { "PowerMac5,1", FTR_CAN_NAP }, /* Cube */ { "AAPL,3400/2400", FTR_CAN_SLEEP }, /* 2400/3400 PowerBook */ { "AAPL,3500", FTR_CAN_SLEEP }, /* 3500 PowerBook (G3) */ { "AAPL,PowerBook1998", FTR_CAN_SLEEP }, /* Wallstreet PowerBook */ { "PowerBook1,1", FTR_CAN_SLEEP }, /* 101 (Lombard) PowerBook */ + { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP| /* New polycarbonate iBook */ + 0/*FTR_HAS_FW_POWER*/ }, { "PowerBook2,1", FTR_CAN_SLEEP }, /* iBook */ - { "PowerBook4,1", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* iBook Dual USB */ { "PowerBook2,2", FTR_CAN_SLEEP /*| FTR_CAN_NAP*/ }, /* iBook FireWire */ { "PowerBook3,1", FTR_CAN_SLEEP|FTR_CAN_NAP| /* PowerBook 2000 (Pismo) */ FTR_HAS_FW_POWER }, - { "PowerBook3,2", FTR_CAN_NAP|FTR_CAN_SLEEP }, /* PowerBook Titanium */ + { "PowerBook3,2", FTR_CAN_NAP|FTR_CAN_SLEEP| /* PowerBook Titanium */ + 0/*FTR_HAS_FW_POWER*/ }, { NULL, 0 } }; @@ -305,15 +327,25 @@ struct device_node *np; u32 *rev; int i; - + char* model; + if (_machine != _MACH_Pmac) return; - /* Figure out motherboard type & options */ - for(i=0;board_features_datas[i].compatible;i++) { - if (machine_is_compatible(board_features_datas[i].compatible)) { - board_features = board_features_datas[i].features; - break; + np = find_path_device("/"); + if (!np) { + printk(KERN_ERR "feature.c: Can't find device-tree root !\n"); + return; + } + model = (char*)get_property(np, "model", NULL); + if (model) { + printk("PowerMac model: %s\n", model); + /* Figure out motherboard type & options */ + for(i=0;board_features_datas[i].compatible;i++) { + if (!strcmp(board_features_datas[i].compatible, model)) { + board_features = board_features_datas[i].features; + break; + } } } @@ -382,8 +414,9 @@ printk("Uninorth at 0x%08x\n", np->addrs[0].address); } if (uninorth_base && keylargo_base) - printk("Uni-N revision: %d, KeyLargo revision: %d\n", - uninorth_rev, keylargo_rev); + printk("Uni-N revision: %d, KeyLargo revision: %d %s\n", + uninorth_rev, keylargo_rev, + (keylargo_rev & KL_PANGEA_REV) ? "(Pangea chipset)" : ""); if (uninorth_base) uninorth_init(); @@ -402,6 +435,25 @@ feature_clear(controllers[0].device, FEATURE_Sound_CLK_enable); } #endif + +#ifdef CONFIG_PMAC_PBOOK + /* On PowerBooks, we disable the serial ports by default, they + * will be re-enabled by the driver + */ +#ifndef CONFIG_XMON + if (controller_count && find_devices("via-pmu") != NULL) { + feature_set_modem_power(NULL, 0); + feature_clear(controllers[0].device, FEATURE_Serial_IO_A); + feature_clear(controllers[0].device, FEATURE_Serial_IO_B); + feature_clear(controllers[0].device, FEATURE_Serial_enable); + if (controller_count > 1) { + feature_clear(controllers[1].device, FEATURE_Serial_IO_A); + feature_clear(controllers[1].device, FEATURE_Serial_IO_B); + feature_clear(controllers[1].device, FEATURE_Serial_enable); + } + } +#endif +#endif } static struct feature_controller __init * @@ -588,12 +640,16 @@ /* TODO: Handle save/restore of PCI config space here */ - spin_lock_irqsave(&keylargo->lock, flags); + /* XXX We use the keylargo spinlock, but we never + * have uninorth without keylargo, so... + */ + KL_LOCK(); if (power) UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); else UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); - spin_unlock_irqrestore(&keylargo->lock, flags); + (void)UN_IN(UNI_N_CLOCK_CNTL); + KL_UNLOCK(); udelay(20); } @@ -605,17 +661,16 @@ if (!keylargo_base || !keylargo) return; - spin_lock_irqsave(&keylargo->lock, flags); - out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), - KEYLARGO_GPIO_OUTPUT_ENABLE); - (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET)); - spin_unlock_irqrestore(&keylargo->lock, flags); + KL_LOCK(); + KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET); + KL_UNLOCK(); mdelay(10); - spin_lock_irqsave(&keylargo->lock, flags); - out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), + KL_LOCK(); + KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); - (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET)); - spin_unlock_irqrestore(&keylargo->lock, flags); + (void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET); + KL_UNLOCK(); mdelay(10); } @@ -642,17 +697,23 @@ else return; - spin_lock_irqsave(&keylargo->lock, flags); + KL_LOCK(); if (power) { /* Turn ON */ if (number == 0) { KL_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); + (void)KL_IN(KEYLARGO_FCR0); + KL_UNLOCK(); mdelay(1); + KL_LOCK(); KL_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); } else { KL_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); + KL_UNLOCK(); + (void)KL_IN(KEYLARGO_FCR0); mdelay(1); + KL_LOCK(); KL_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); } reg = KL_IN(KEYLARGO_FCR4); @@ -689,7 +750,7 @@ } udelay(1); } - spin_unlock_irqrestore(&keylargo->lock, flags); + KL_UNLOCK(); } void __pmac @@ -697,18 +758,25 @@ { unsigned long flags; - /* TODO: Handle save/restore of PCI config space here + /* TODO: should probably handle save/restore of PCI config space here */ + if (!uninorth_fw || (device && uninorth_fw != device)) + return; if (!uninorth_base) return; - spin_lock_irqsave(&keylargo->lock, flags); + + /* XXX We use the keylargo spinlock, but we never + * have uninorth without keylargo, so... + */ + KL_LOCK(); if (power) UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); else UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); + (void)UN_IN(UNI_N_CLOCK_CNTL); + KL_UNLOCK(); udelay(20); - spin_unlock_irqrestore(&keylargo->lock, flags); } /* Warning: will kill the PHY.. */ @@ -717,79 +785,159 @@ { unsigned long flags; u8 gpioValue = power ? 0 : 4; - + + if (!uninorth_fw || (device && uninorth_fw != device)) + return; if (!keylargo_base || !(board_features & FTR_HAS_FW_POWER)) return; - spin_lock_irqsave(&keylargo->lock, flags); - out_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER), gpioValue); - (void)in_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER)); - spin_unlock_irqrestore(&keylargo->lock, flags); + KL_LOCK(); + KL_GPIO_OUT(KL_GPIO_FW_CABLE_POWER, gpioValue); + (void)KL_GPIO_IN(KL_GPIO_FW_CABLE_POWER); + KL_UNLOCK(); +} + +void +feature_set_modem_power(struct device_node* device, int power) +{ + unsigned long flags; + + if (!device) { + device = find_devices("ch-a"); + while(device && !device_is_compatible(device, "cobalt")) + device = device->next; + if (!device) + return; + } + if (keylargo && (keylargo_rev & KL_PANGEA_REV)) { + KL_LOCK(); + if (power) { + /* Assert modem reset */ + KL_GPIO_OUT(KL_GPIO_MODEM_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(KL_GPIO_MODEM_RESET); + udelay(10); + /* Power up modem */ + KL_GPIO_OUT(KL_GPIO_MODEM_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(KL_GPIO_MODEM_POWER); + udelay(10); + /* Release modem reset */ + KL_GPIO_OUT(KL_GPIO_MODEM_RESET, + KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + (void)KL_GPIO_IN(KL_GPIO_MODEM_RESET); + } else { + /* Power down modem */ + KL_GPIO_OUT(KL_GPIO_MODEM_POWER, + KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + (void)KL_GPIO_IN(KL_GPIO_MODEM_POWER); + } + KL_UNLOCK(); + } else { + if (power) { + mdelay(300); + feature_set(device, FEATURE_Modem_power); + mdelay(5); + feature_clear(device, FEATURE_Modem_power); + mdelay(10); + feature_set(device, FEATURE_Modem_power); + } else { + feature_clear(device, FEATURE_Modem_power); + mdelay(10); + } + } } #ifdef CONFIG_SMP void __pmac feature_core99_kick_cpu(int cpu_nr) { -#if 1 /* New way */ const int reset_lines[] = { KL_GPIO_RESET_CPU0, KL_GPIO_RESET_CPU1, KL_GPIO_RESET_CPU2, KL_GPIO_RESET_CPU3 }; - volatile u8* reset_io; - + int reset_io; + unsigned long flags; + if (!keylargo_base || cpu_nr > 3) return; - reset_io = (volatile u8*)KL_FCR(reset_lines[cpu_nr]); - out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); - udelay(1); - out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); -#else - out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_ASSERT); + reset_io = reset_lines[cpu_nr]; + + KL_LOCK(); + KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)KL_GPIO_IN(reset_io); udelay(1); - out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_RELEASE); -#endif + KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); + (void)KL_GPIO_IN(reset_io); + KL_UNLOCK(); } #endif /* CONFIG_SMP */ void __pmac feature_set_airport_power(struct device_node* device, int power) { + unsigned long flags; + if (!keylargo_base || !airport_dev || airport_dev != device) return; if (airport_pwr_state == power) - return; + return; if (power) { - /* Some if this is from Darwin code, some is from tracing of - * MacOS driver with Macsbug. Some real bit definitions would - * really help here... + /* This code is a reproduction of OF enable-cardslot + * and init-wireless methods, slightly hacked until + * I got it working. */ - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), airport_pwr_regs[0]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), airport_pwr_regs[1]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), airport_pwr_regs[2]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), airport_pwr_regs[3]); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), airport_pwr_regs[4]); - udelay(20); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 5); - udelay(20); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 4); - mdelay(20); + KL_LOCK(); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 5); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf); + KL_UNLOCK(); + mdelay(10); + KL_LOCK(); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 4); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf); + KL_UNLOCK(); + + mdelay(10); + + KL_LOCK(); KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N); + (void)KL_IN(KEYLARGO_FCR2); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xb, 0); + (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xb); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xa); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xd); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xd, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xd); + udelay(10); + KL_GPIO_OUT(KEYLARGO_GPIO_0+0xe, 0x28); + (void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xe); + KL_UNLOCK(); udelay(10); + KL_OUT(0x1c000, 0); + + mdelay(1); out_8((volatile u8*)KL_FCR(0x1a3e0), 0x41); + (void)in_8((volatile u8*)KL_FCR(0x1a3e0)); udelay(10); + KL_LOCK(); KL_BIS(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N); - udelay(10); + (void)KL_IN(KEYLARGO_FCR2); + KL_UNLOCK(); + mdelay(100); } else { - airport_pwr_regs[0] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0)); - airport_pwr_regs[1] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1)); - airport_pwr_regs[2] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2)); - airport_pwr_regs[3] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3)); - airport_pwr_regs[4] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4)); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), 0); - out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 0); + KL_LOCK(); + KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N); + (void)KL_IN(KEYLARGO_FCR2); + KL_GPIO_OUT(KL_GPIO_AIRPORT_0, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_1, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_2, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_3, 0); + KL_GPIO_OUT(KL_GPIO_AIRPORT_4, 0); + (void)KL_GPIO_IN(KL_GPIO_AIRPORT_4); + KL_UNLOCK(); } airport_pwr_state = power; } @@ -826,8 +974,11 @@ /* Enable FW before PCI probe. Will be disabled later on */ fw = find_devices("firewire"); - if (fw && device_is_compatible(fw, "pci106b,18")) + if (fw && (device_is_compatible(fw, "pci106b,18") || + device_is_compatible(fw, "pci106b,30"))) { + uninorth_fw = fw; feature_set_firewire_power(fw, 1); + } } /* Initialize the Core99 KeyLargo ASIC. @@ -864,7 +1015,7 @@ device_is_compatible(ctrler->device, "gatwick")) ctrler = &controllers[1]; - if (ctrler->bits == feature_bits_heathrow || + if (ctrler->bits == feature_bits_wallstreet || ctrler->bits == feature_bits_paddington) { heathrow_prepare_for_sleep(ctrler); return; @@ -884,7 +1035,7 @@ device_is_compatible(ctrler->device, "gatwick")) ctrler = &controllers[1]; - if (ctrler->bits == feature_bits_heathrow || + if (ctrler->bits == feature_bits_wallstreet || ctrler->bits == feature_bits_paddington) { heathrow_wakeup(ctrler); return; @@ -929,15 +1080,10 @@ { u32 temp; - /* For now, suspending the USB ref cause the machine to die on - * wakeup -- BenH - */ -#if 0 mdelay(1); KL_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); (void)KL_IN(KEYLARGO_FCR0); - mdelay(1500); -#endif + mdelay(100); KL_BIC(KEYLARGO_FCR0, KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | KL0_SCC_CELL_ENABLE | @@ -1014,7 +1160,7 @@ core99_prepare_for_sleep(struct feature_controller* ctrler) { int i; - u8* base8; + volatile u8* base8; /* * Save various bits of KeyLargo @@ -1026,15 +1172,19 @@ feature_set_airport_power(airport_dev, 0); /* We power off the FW cable. Should be done by the driver... */ + feature_set_firewire_power(NULL, 0); feature_set_firewire_cable_power(NULL, 0); + + /* We make sure int. modem is off (in case driver lost it) */ + feature_set_modem_power(NULL, 0); /* Save the state of the various GPIOs */ save_gpio_levels[0] = KL_IN(KEYLARGO_GPIO_LEVELS0); save_gpio_levels[1] = KL_IN(KEYLARGO_GPIO_LEVELS1); - base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_EXTINT_0); + base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_EXTINT_0; for (i=0; i> 28) & 0xf; + pvr = mfspr(PVR); + hid1 = (mfspr(HID1) >> 28) & 0xf; if (PVR_VER(pvr) == 8 || PVR_VER(pvr) == 12) hid1 = cpu_7xx[hid1]; @@ -241,11 +231,12 @@ { unsigned char reg, brev, fam, creg; unsigned long cache; - unsigned long pvr = _get_PVR(); + unsigned long pvr; reg = readb(GEMINI_L2CFG); brev = readb(GEMINI_BREV); fam = readb(GEMINI_FEAT); + pvr = mfspr(PVR); switch(PVR_VER(pvr)) { @@ -486,11 +477,60 @@ return total; } -void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +static void __init +gemini_map_io(void) +{ + io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); + io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); +} + +#ifdef CONFIG_SMP +static int +smp_gemini_probe(void) +{ + int i, nr; + + nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; + if (nr == 0) + nr = 4; + + if (nr > 1) { + openpic_request_IPIs(); + for (i = 1; i < nr; ++i) + smp_hw_index[i] = i; + } + + return nr; +} + +static void +smp_gemini_kick_cpu(int nr) +{ + openpic_init_processor( 1< 0) + gemini_init_l2(); +} + +static struct smp_ops_t gemini_smp_ops = { + smp_openpic_message_pass, + smp_gemini_probe, + smp_gemini_kick_cpu, + smp_gemini_setup_cpu, +}; +#endif /* CONFIG_SMP */ + +void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { int i; - int chrp_get_irq( struct pt_regs * ); for(i = 0; i < GEMINI_LEDS; i++) gemini_led_off(i); @@ -525,6 +565,7 @@ ppc_md.calibrate_decr = gemini_calibrate_decr; ppc_md.find_end_of_memory = gemini_find_end_of_memory; + ppc_md.setup_io_mappings = gemini_map_io; /* no keyboard/mouse/video stuff yet.. */ ppc_md.kbd_setkeycode = NULL; @@ -537,4 +578,8 @@ ppc_md.ppc_kbd_sysrq_xlate = NULL; #endif ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup; + +#ifdef CONFIG_SMP + ppc_md.smp_ops = &gemini_smp_ops; +#endif /* CONFIG_SMP */ } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.4.9/linux/arch/ppc/kernel/head.S Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/head.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head.S 1.25 07/07/01 17:08:44 paulus + * BK Id: SCCS/s.head.S 1.29 08/19/01 22:43:23 paulus */ /* * PowerPC version @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_APUS #include @@ -153,7 +154,7 @@ #ifndef CONFIG_GEMINI /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains - * the physical address we are running at, returned by prom_init() + * the physical address we are running at, returned by early_init() */ bl mmu_off __after_mmu_off: @@ -761,12 +762,10 @@ addi r24,r1,STACK_FRAME_OVERHEAD stw r24,PT_REGS(r23) #ifdef CONFIG_ALTIVEC - mfpvr r24 /* check if we are on a G4 */ - srwi r24,r24,16 - cmpwi r24,PVR_7400@h - bne 2f - mfspr r22,SPRN_VRSAVE /* if so, save vrsave register value */ +BEGIN_FTR_SECTION + mfspr r22,SPRN_VRSAVE /* if G4, save vrsave register value */ stw r22,THREAD_VRSAVE(r23) +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ 2: addi r2,r23,-THREAD /* set r2 to current */ tovirt(r2,r2) @@ -1280,10 +1279,13 @@ SYNC MTMSRD(r0) isync -#else - bl enable_caches #endif + lis r3,-KERNELBASE@h + mr r4,r24 + bl identify_cpu + bl call_setup_cpu /* Call setup_cpu for this CPU */ + /* get current */ lis r2,current_set@h ori r2,r2,current_set@l @@ -1322,54 +1324,87 @@ /* * Enable caches and 604-specific features if necessary. */ -enable_caches: - mfspr r9,PVR - rlwinm r9,r9,16,16,31 - cmpi 0,r9,1 - beq 6f /* not needed for 601 */ +_GLOBAL(__setup_cpu_601) + blr +_GLOBAL(__setup_cpu_603) + b setup_common_caches +_GLOBAL(__setup_cpu_604) + mflr r4 + bl setup_common_caches + bl setup_604_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_750) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7400) + mflr r4 + bl setup_common_caches + bl setup_750_7400_hid0 + mtlr r4 + blr +_GLOBAL(__setup_cpu_7450) + blr +_GLOBAL(__setup_cpu_power3) + blr +_GLOBAL(__setup_cpu_power4) + blr +_GLOBAL(__setup_cpu_generic) + blr + +/* Enable caches for 603's, 604, 750 & 7400 */ +setup_common_caches: mfspr r11,HID0 andi. r0,r11,HID0_DCE ori r11,r11,HID0_ICE|HID0_DCE ori r8,r11,HID0_ICFI - bne 3f /* don't invalidate the D-cache */ + bne 1f /* don't invalidate the D-cache */ ori r8,r8,HID0_DCI /* unless it wasn't enabled */ -3: - sync +1: sync mtspr HID0,r8 /* enable and invalidate caches */ sync mtspr HID0,r11 /* enable caches */ sync isync - cmpi 0,r9,4 /* check for 604 */ - cmpi 1,r9,9 /* or 604e */ - cmpi 2,r9,10 /* or mach5 / 604r */ - cmpi 3,r9,8 /* check for 750 (G3) */ - cmpi 4,r9,12 /* or 7400 (G4) */ - cror 2,2,6 - cror 2,2,10 - bne 4f - ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e|r], enable */ - bne 2,5f - ori r11,r11,HID0_BTCD /* superscalar exec & br history tbl */ - b 5f -4: - cror 14,14,18 - bne 3,6f - /* for G3/G4: - * enable Store Gathering (SGE), Address Brodcast (ABE), - * Branch History Table (BHTE), Branch Target ICache (BTIC) - */ + blr + +/* 604, 604e, 604ev, ... + * Enable superscalar execution & branch history table + */ +setup_604_hid0: + mfspr r11,HID0 + ori r11,r11,HID0_SIED|HID0_BHTE + ori r8,r11,HID0_BTCD + sync + mtspr HID0,r8 /* flush branch target address cache */ + sync /* on 604e/604r */ + mtspr HID0,r11 + sync + isync + blr + +/* 740/750/7400/7410 + * Enable Store Gathering (SGE), Address Brodcast (ABE), + * Branch History Table (BHTE), Branch Target ICache (BTIC) + * Dynamic Power Management (DPM), Speculative (SPD) + * Clear Instruction cache throttling (ICTC) + */ +setup_750_7400_hid0: + mfspr r11,HID0 ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ li r3,HID0_SPD andc r11,r11,r3 /* clear SPD: enable speculative */ li r3,0 mtspr ICTC,r3 /* Instruction Cache Throttling off */ -5: isync + isync mtspr HID0,r11 sync isync -6: blr + blr /* * Load stuff into the MMU. Intended to be called with @@ -1414,9 +1449,10 @@ * This is where the main kernel code starts. */ start_here: -#ifndef CONFIG_PPC64BRIDGE - bl enable_caches -#endif + /* Call setup_cpu for CPU 0 */ + li r3,0 /* data offset */ + li r24,0 /* cpu# */ + bl call_setup_cpu /* ptr to current */ lis r2,init_task_union@h @@ -1435,14 +1471,15 @@ li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) /* - * Decide what sort of machine this is and initialize the MMU. + * Do early bootinfo parsing, platform-specific initialization, + * and set up the MMU. */ mr r3,r31 mr r4,r30 mr r5,r29 mr r6,r28 mr r7,r27 - bl identify_machine + bl machine_init bl MMU_init #ifdef CONFIG_APUS @@ -1475,12 +1512,10 @@ /* Load up the kernel context */ 2: sync /* Force all PTE updates to finish */ + ISYNC_601 tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ -#ifdef CONFIG_SMP - tlbsync /* ... on all CPUs */ - sync -#endif + TLBSYNC /* ... on all CPUs */ bl load_up_mmu /* Now turn on the MMU for real! */ @@ -1500,7 +1535,7 @@ mulli r3,r3,897 /* multiply context by skew factor */ rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */ addis r3,r3,0x6000 /* Set Ks, Ku bits */ - li r0,12 /* TASK_SIZE / SEGMENT_SIZE */ + li r0,NUM_USER_SEGMENTS mtctr r0 li r4,0 3: @@ -1512,7 +1547,8 @@ rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b - SYNC + SYNC_601 + isync blr /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S --- v2.4.9/linux/arch/ppc/kernel/head_8xx.S Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/head_8xx.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.head_8xx.S 1.14 06/28/01 15:50:16 paulus + * BK Id: SCCS/s.head_8xx.S 1.19 08/16/01 23:00:17 paulus */ /* * arch/ppc/kernel/except_8xx.S @@ -31,6 +31,7 @@ #include #include #include +#include .text .globl _stext @@ -87,70 +88,10 @@ mr r27,r7 li r24,0 /* cpu # */ - tlbia /* Invalidate all TLB entries */ - li r8, 0 - mtspr MI_CTR, r8 /* Set instruction control to zero */ - lis r8, MD_RESETVAL@h -#ifndef CONFIG_8xx_COPYBACK - oris r8, r8, MD_WTDEF@h -#endif - mtspr MD_CTR, r8 /* Set data TLB control */ - - /* Now map the lower 8 Meg into the TLBs. For this quick hack, - * we can load the instruction and data TLB registers with the - * same values. - */ - lis r8, KERNELBASE@h /* Create vaddr for TLB */ - ori r8, r8, MI_EVALID /* Mark it valid */ - mtspr MI_EPN, r8 - mtspr MD_EPN, r8 - li r8, MI_PS8MEG /* Set 8M byte page */ - ori r8, r8, MI_SVALID /* Make it valid */ - mtspr MI_TWC, r8 - mtspr MD_TWC, r8 - li r8, MI_BOOTINIT /* Create RPN for address 0 */ - mtspr MI_RPN, r8 /* Store TLB entry */ - mtspr MD_RPN, r8 - lis r8, MI_Kp@h /* Set the protection mode */ - mtspr MI_AP, r8 - mtspr MD_AP, r8 - - /* Map another 8 MByte at the IMMR to get the processor - * internal registers (among other things). + /* We have to turn on the MMU right away so we get cache modes + * set correctly. */ - mfspr r9, 638 /* Get current IMMR */ - andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */ - - mr r8, r9 /* Create vaddr for TLB */ - ori r8, r8, MD_EVALID /* Mark it valid */ - mtspr MD_EPN, r8 - li r8, MD_PS8MEG /* Set 8M byte page */ - ori r8, r8, MD_SVALID /* Make it valid */ - mtspr MD_TWC, r8 - mr r8, r9 /* Create paddr for TLB */ - ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ - mtspr MD_RPN, r8 - - /* Since the cache is enabled according to the information we - * just loaded into the TLB, invalidate and enable the caches here. - * We should probably check/set other modes....later. - */ - lis r8, IDC_INVALL@h - mtspr IC_CST, r8 - mtspr DC_CST, r8 - lis r8, IDC_ENABLE@h - mtspr IC_CST, r8 -#ifdef CONFIG_8xx_COPYBACK - mtspr DC_CST, r8 -#else - /* For a debug option, I left this here to easily enable - * the write through cache mode - */ - lis r8, DC_SFWT@h - mtspr DC_CST, r8 - lis r8, IDC_ENABLE@h - mtspr DC_CST, r8 -#endif + bl initial_mmu /* We now have the lower 8 Meg mapped into TLB entries, and the caches * ready to work. @@ -513,6 +454,7 @@ #else li r21, 0x00f0 rlwimi r20, r21, 0, 24, 28 + #endif #ifdef CONFIG_8xx_CPU6 li r3, 0x3d80 @@ -721,131 +663,34 @@ giveup_fpu: blr -/* - * This code is jumped to from the startup code to copy - * the kernel image to physical address 0. - */ -relocate_kernel: - lis r9,0x426f /* if booted from BootX, don't */ - addi r9,r9,0x6f58 /* translate source addr */ - cmpw r31,r9 /* (we have to on chrp) */ - beq 7f - rlwinm r4,r4,0,8,31 /* translate source address */ - add r4,r4,r3 /* to region mapped with BATs */ -7: addis r9,r26,klimit@ha /* fetch klimit */ - lwz r25,klimit@l(r9) - addis r25,r25,-KERNELBASE@h - li r6,0 /* Destination offset */ - li r5,0x4000 /* # bytes of memory to copy */ - bl copy_and_flush /* copy the first 0x4000 bytes */ - addi r0,r3,4f@l /* jump to the address of 4f */ - mtctr r0 /* in copy and do the rest. */ - bctr /* jump to the copy */ -4: mr r5,r25 - bl copy_and_flush /* copy the rest */ - b turn_on_mmu - -/* - * Copy routine used to copy the kernel to start at physical address 0 - * and flush and invalidate the caches as needed. - * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset - * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. - */ -copy_and_flush: - addi r5,r5,-4 - addi r6,r6,-4 -4: li r0,CACHE_LINE_SIZE/4 - mtctr r0 -3: addi r6,r6,4 /* copy a cache line */ - lwzx r0,r6,r4 - stwx r0,r6,r3 - bdnz 3b - dcbst r6,r3 /* write it to memory */ - sync - icbi r6,r3 /* flush the icache line */ - cmplw 0,r6,r5 - blt 4b - isync - addi r5,r5,4 - addi r6,r6,4 +/* Maybe someday....... +*/ +_GLOBAL(__setup_cpu_8xx) blr -#ifdef CONFIG_SMP - .globl __secondary_start_psurge -__secondary_start_psurge: - li r24,1 /* cpu # */ - b __secondary_start - - .globl __secondary_hold -__secondary_hold: - /* tell the master we're here */ - lis r5,0x4@h - ori r5,r5,0x4@l - stw r3,0(r5) - dcbf 0,r5 -100: - lis r5,0 - dcbi 0,r5 - lwz r4,0(r5) - /* wait until we're told to start */ - cmp 0,r4,r3 - bne 100b - /* our cpu # was at addr 0 - go */ - lis r5,__secondary_start@h - ori r5,r5,__secondary_start@l - tophys(r5,r5) - mtlr r5 - mr r24,r3 /* cpu # */ - blr -#endif /* CONFIG_SMP */ - /* * This is where the main kernel code starts. */ start_here: -#ifdef CONFIG_SMP - /* if we're the second cpu stack and r2 are different - * and we want to not clear the bss -- Cort */ - lis r5,first_cpu_booted@h - ori r5,r5,first_cpu_booted@l - lwz r5,0(r5) - cmpi 0,r5,0 - beq 99f - - /* get current */ - lis r2,current_set@h - ori r2,r2,current_set@l - slwi r24,r24,2 /* cpu # to current_set[cpu#] */ - add r2,r2,r24 - lwz r2,0(r2) - b 10f -99: -#endif /* CONFIG_SMP */ + /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l - /* Clear out the BSS */ - lis r11,_end@ha - addi r11,r11,_end@l - lis r8,__bss_start@ha - addi r8,r8,__bss_start@l - subf r11,r8,r11 - addi r11,r11,3 - rlwinm. r11,r11,30,2,31 - beq 2f - addi r8,r8,-4 - mtctr r11 - li r0,0 -3: stwu r0,4(r8) - bdnz 3b -2: -#ifdef CONFIG_SMP -10: -#endif /* CONFIG_SMP */ + + /* ptr to phys current thread */ + tophys(r4,r2) + addi r4,r4,THREAD /* init task's THREAD */ + mtspr SPRG3,r4 + li r3,0 + mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ + /* stack */ addi r1,r2,TASK_UNION_SIZE li r0,0 stwu r0,-STACK_FRAME_OVERHEAD(r1) + + bl early_init /* We have to do this with MMU on */ + /* * Decide what sort of machine this is and initialize the MMU. */ @@ -854,12 +699,11 @@ mr r5,r29 mr r6,r28 mr r7,r27 - bl identify_machine + bl machine_init bl MMU_init /* * Go back to running unmapped so we can load up new values - * for SDR1 (hash table pointer) and the segment registers * and change to using our exception vectors. * On the 8xx, all we have to do is invalidate the TLB to clear * the old 8M byte TLB mappings and load the page table base register. @@ -869,8 +713,8 @@ * easier......until someone changes init's static structures. */ lis r6, swapper_pg_dir@h - tophys(r6,r6) ori r6, r6, swapper_pg_dir@l + tophys(r6,r6) #ifdef CONFIG_8xx_CPU6 lis r4, cpu6_errata_word@h ori r4, r4, cpu6_errata_word@l @@ -891,65 +735,117 @@ SYNC /* Force all PTE updates to finish */ tlbia /* Clear all TLB entries */ sync /* wait for tlbia/tlbie to finish */ -#ifdef CONFIG_SMP - tlbsync /* ... on all CPUs */ - sync -#endif -/* Set up for using our exception vectors */ - /* ptr to phys current thread */ - tophys(r4,r2) - addi r4,r4,THREAD /* init task's THREAD */ - mtspr SPRG3,r4 - li r3,0 - mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ + TLBSYNC /* ... on all CPUs */ + + /* set up the PTE pointers for the Abatron bdiGDB. + */ + tovirt(r6,r6) + lis r5, abatron_pteptrs@h + ori r5, r5, abatron_pteptrs@l + stw r5, 0xf0(r0) /* Must match your Abatron config file */ + tophys(r5,r5) + stw r6, 0(r5) + /* Now turn on the MMU for real! */ li r4,MSR_KERNEL lis r3,start_kernel@h ori r3,r3,start_kernel@l -#ifdef CONFIG_SMP - /* the second time through here we go to - * start_secondary(). -- Cort - */ - lis r5,first_cpu_booted@h - ori r5,r5,first_cpu_booted@l - tophys(r5,r5) - lwz r5,0(r5) - cmpi 0,r5,0 - beq 10f - lis r3,start_secondary@h - ori r3,r3,start_secondary@l -10: -#endif /* CONFIG_SMP */ mtspr SRR0,r3 mtspr SRR1,r4 rfi /* enable MMU and jump to start_kernel */ +/* Set up the initial MMU state so we can do the first level of + * kernel initialization. This maps the first 8 MBytes of memory 1:1 + * virtual to physical. Also, set the cache mode since that is defined + * by TLB entries and perform any additional mapping (like of the IMMR). + */ +initial_mmu: + tlbia /* Invalidate all TLB entries */ + li r8, 0 + mtspr MI_CTR, r8 /* Set instruction control to zero */ + lis r8, MD_RESETVAL@h +#ifndef CONFIG_8xx_COPYBACK + oris r8, r8, MD_WTDEF@h +#endif + mtspr MD_CTR, r8 /* Set data TLB control */ + + /* Now map the lower 8 Meg into the TLBs. For this quick hack, + * we can load the instruction and data TLB registers with the + * same values. + */ + lis r8, KERNELBASE@h /* Create vaddr for TLB */ + ori r8, r8, MI_EVALID /* Mark it valid */ + mtspr MI_EPN, r8 + mtspr MD_EPN, r8 + li r8, MI_PS8MEG /* Set 8M byte page */ + ori r8, r8, MI_SVALID /* Make it valid */ + mtspr MI_TWC, r8 + mtspr MD_TWC, r8 + li r8, MI_BOOTINIT /* Create RPN for address 0 */ + mtspr MI_RPN, r8 /* Store TLB entry */ + mtspr MD_RPN, r8 + lis r8, MI_Kp@h /* Set the protection mode */ + mtspr MI_AP, r8 + mtspr MD_AP, r8 + + /* Map another 8 MByte at the IMMR to get the processor + * internal registers (among other things). + */ + mfspr r9, 638 /* Get current IMMR */ + andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */ + + mr r8, r9 /* Create vaddr for TLB */ + ori r8, r8, MD_EVALID /* Mark it valid */ + mtspr MD_EPN, r8 + li r8, MD_PS8MEG /* Set 8M byte page */ + ori r8, r8, MD_SVALID /* Make it valid */ + mtspr MD_TWC, r8 + mr r8, r9 /* Create paddr for TLB */ + ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ + mtspr MD_RPN, r8 + + /* Since the cache is enabled according to the information we + * just loaded into the TLB, invalidate and enable the caches here. + * We should probably check/set other modes....later. + */ + lis r8, IDC_INVALL@h + mtspr IC_CST, r8 + mtspr DC_CST, r8 + lis r8, IDC_ENABLE@h + mtspr IC_CST, r8 +#ifdef CONFIG_8xx_COPYBACK + mtspr DC_CST, r8 +#else + /* For a debug option, I left this here to easily enable + * the write through cache mode + */ + lis r8, DC_SFWT@h + mtspr DC_CST, r8 + lis r8, IDC_ENABLE@h + mtspr DC_CST, r8 + blr +#endif + + /* * Set up to use a given MMU context. + * r3 is context number, r4 is PGD pointer. * - * The MPC8xx has something that currently happens "automagically." - * Unshared user space address translations are subject to ASID (context) - * match. During each task switch, the ASID is incremented. We can - * guarantee (I hope :-) that no entries currently match this ASID - * because every task will cause at least a TLB entry to be loaded for - * the first instruction and data access, plus the kernel running will - * have displaced several more TLBs. The MMU contains 32 entries for - * each TLB, and there are 16 contexts, so we just need to make sure - * two pages get replaced for every context switch, which currently - * happens. There are other TLB management techniques that I will - * eventually implement, but this is the easiest for now. -- Dan - * - * On the MPC8xx, we place the physical address of the new task - * page directory loaded into the MMU base register, and set the - * ASID compare register with the new "context". + * We place the physical address of the new task page directory loaded + * into the MMU base register, and set the ASID compare register with + * the new "context." */ _GLOBAL(set_context) - /* fetch the pgd from the context_mm array */ - lis r5, context_mm@ha - slwi r6, r3, 2 - add r5, r5, r6 - lwz r5, context_mm@l(r5) /* get the mm */ - lwz r4, MM_PGD(r5) /* get the pgd from the mm */ + +#ifdef CONFIG_BDI_SWITCH + /* Context switch the PTE pointer for the Abatron BDI2000. + * The PGDIR is passed as second argument. + */ + lis r5, KERNELBASE@h + lwz r5, 0xf0(r5) + stw r4, 0x4(r5) +#endif + #ifdef CONFIG_8xx_CPU6 lis r6, cpu6_errata_word@h ori r6, r6, cpu6_errata_word@l @@ -967,7 +863,6 @@ tophys (r4, r4) mtspr M_TWB, r4 /* and pgd */ #endif - tlbia SYNC blr @@ -1012,6 +907,12 @@ .globl cmd_line cmd_line: .space 512 + +/* Room for two PTE table poiners, usually the kernel and current user + * pointer to their respective root page table (pgdir). + */ +abatron_pteptrs: + .space 8 #ifdef CONFIG_8xx_CPU6 .globl cpu6_errata_word diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.4.9/linux/arch/ppc/kernel/idle.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/idle.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.idle.c 1.11 05/17/01 18:14:21 cort + * BK Id: SCCS/s.idle.c 1.14 08/15/01 22:43:06 paulus */ /* * Idle daemon for PowerPC. Idle daemon will handle any action @@ -31,12 +31,11 @@ #include #include #include +#include void zero_paged(void); void power_save(void); -void inline htab_reclaim(void); -unsigned long htab_reclaim_on = 0; unsigned long zero_paged_on = 0; unsigned long powersave_nap = 0; @@ -50,27 +49,30 @@ { int do_power_save = 0; - /* only sleep on the 603-family/750 processors */ - switch (_get_PVR() >> 16) { - case 3: /* 603 */ - case 6: /* 603e */ - case 7: /* 603ev */ - case 8: /* 750 */ - case 12: /* 7400 */ - case 0x800c: /* 7410 */ + if (cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_CAN_DOZE) do_power_save = 1; - } /* endless loop with no priority at all */ current->nice = 20; current->counter = -100; - init_idle(); - for (;;) - { - /*if ( !current->need_resched && zero_paged_on ) - zero_paged();*/ - if (!current->need_resched && htab_reclaim_on) - htab_reclaim(); + init_idle(); + for (;;) { +#ifdef CONFIG_SMP + int oldval; + + if (!do_power_save) { + /* + * Deal with another CPU just having chosen a thread to + * run here: + */ + oldval = xchg(¤t->need_resched, -1); + + if (!oldval) { + while(current->need_resched == -1) + ; /* Do Nothing */ + } + } +#endif if (do_power_save && !current->need_resched) power_save(); @@ -92,68 +94,6 @@ return 0; } -/* - * Mark 'zombie' pte's in the hash table as invalid. - * This improves performance for the hash table reload code - * a bit since we don't consider unused pages as valid. - * -- Cort - */ -PTE *reclaim_ptr = 0; -void inline htab_reclaim(void) -{ -#ifndef CONFIG_8xx -#if 0 - PTE *ptr, *start; - static int dir = 1; -#endif - struct task_struct *p; - unsigned long valid = 0; - extern PTE *Hash, *Hash_end; - extern unsigned long Hash_size; - - /* if we don't have a htab */ - if ( Hash_size == 0 ) - return; -#if 0 - /* find a random place in the htab to start each time */ - start = &Hash[jiffies%(Hash_size/sizeof(PTE))]; - /* go a different direction each time */ - dir *= -1; - for ( ptr = start; - !current->need_resched && (ptr != Hash_end) && (ptr != Hash); - ptr += dir) - { -#else - if ( !reclaim_ptr ) reclaim_ptr = Hash; - while ( !current->need_resched ) - { - reclaim_ptr++; - if ( reclaim_ptr == Hash_end ) reclaim_ptr = Hash; -#endif - if (!reclaim_ptr->v) - continue; - valid = 0; - for_each_task(p) - { - if ( current->need_resched ) - goto out; - /* if this vsid/context is in use */ - if ( (reclaim_ptr->vsid >> 4) == p->mm->context ) - { - valid = 1; - break; - } - } - if ( valid ) - continue; - /* this pte isn't used */ - reclaim_ptr->v = 0; - } -out: - if ( current->need_resched ) printk("need_resched: %lx\n", current->need_resched); -#endif /* CONFIG_8xx */ -} - #if 0 /* * Returns a pre-zero'd page from the list otherwise returns @@ -287,7 +227,7 @@ atomic_inc((atomic_t *)&zero_cache_total); } } -#endif +#endif /* 0 */ void power_save(void) { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.4.9/linux/arch/ppc/kernel/irq.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/irq.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.irq.c 1.30 07/19/01 16:51:32 paulus + * BK Id: SCCS/s.irq.c 1.32 08/24/01 20:07:37 paulus */ /* * arch/ppc/kernel/irq.c @@ -93,6 +93,11 @@ static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES]; extern int mem_init_done; +#if defined(CONFIG_TAU_INT) +extern int tau_interrupts(unsigned long cpu); +extern int tau_initialized; +#endif + void *irq_kmalloc(size_t size, int pri) { unsigned int i; @@ -402,12 +407,14 @@ } len += sprintf(buf+len, "\n"); } -#ifdef CONFIG_TAU - len += sprintf(buf+len, "TAU: "); - for (j = 0; j < smp_num_cpus; j++) - len += sprintf(buf+len, "%10u ", - tau_interrupts(j)); - len += sprintf(buf+len, "\n"); +#ifdef CONFIG_TAU_INT + if (tau_initialized){ + len += sprintf(buf+len, "TAU: "); + for (j = 0; j < smp_num_cpus; j++) + len += sprintf(buf+len, "%10u ", + tau_interrupts(j)); + len += sprintf(buf+len, " PowerPC Thermal Assist (cpu temp)\n"); + } #endif #ifdef CONFIG_SMP /* should this be per processor send/receive? */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/l2cr.S linux/arch/ppc/kernel/l2cr.S --- v2.4.9/linux/arch/ppc/kernel/l2cr.S Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/l2cr.S Tue Aug 28 06:58:33 2001 @@ -0,0 +1,201 @@ +/* + L2CR functions + Copyright © 1997-1998 by PowerLogix R & D, Inc. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + Thur, Dec. 12, 1998. + - First public release, contributed by PowerLogix. + *********** + Sat, Aug. 7, 1999. + - Terry: Made sure code disabled interrupts before running. (Previously + it was assumed interrupts were already disabled). + - Terry: Updated for tentative G4 support. 4MB of memory is now flushed + instead of 2MB. (Prob. only 3 is necessary). + - Terry: Updated for workaround to HID0[DPM] processor bug + during global invalidates. + *********** + Thu, July 13, 2000. + - Terry: Added isync to correct for an errata. + + Author: Terry Greeniaus (tgree@phys.ualberta.ca) + Please e-mail updates to this file to me, thanks! +*/ +#include +#include +#include "ppc_asm.h" + +/* Usage: + + When setting the L2CR register, you must do a few special + things. If you are enabling the cache, you must perform a + global invalidate. If you are disabling the cache, you must + flush the cache contents first. This routine takes care of + doing these things. When first enabling the cache, make sure + you pass in the L2CR you want, as well as passing in the + global invalidate bit set. A global invalidate will only be + performed if the L2I bit is set in applyThis. When enabling + the cache, you should also set the L2E bit in applyThis. If + you want to modify the L2CR contents after the cache has been + enabled, the recommended procedure is to first call + __setL2CR(0) to disable the cache and then call it again with + the new values for L2CR. Examples: + + _setL2CR(0) - disables the cache + _setL2CR(0xB3A04000) - enables my G3 upgrade card: + - L2E set to turn on the cache + - L2SIZ set to 1MB + - L2CLK set to 1:1 + - L2RAM set to pipelined synchronous late-write + - L2I set to perform a global invalidation + - L2OH set to 0.5 nS + - L2DF set because this upgrade card + requires it + + A similar call should work for your card. You need to know + the correct setting for your card and then place them in the + fields I have outlined above. Other fields support optional + features, such as L2DO which caches only data, or L2TS which + causes cache pushes from the L1 cache to go to the L2 cache + instead of to main memory. +*/ +/* + * Summary: this procedure ignores the L2I bit in the value passed in, + * flushes the cache if it was already enabled, always invalidates the + * cache, then enables the cache if the L2E bit is set in the value + * passed in. + * -- paulus. + */ +_GLOBAL(_set_L2CR) + /* Make sure this is a 750 or 7400 chip */ +BEGIN_FTR_SECTION + li r3,-1 + blr +END_FTR_SECTION_IFCLR(CPU_FTR_L2CR) + + /* Turn off interrupts and data relocation. */ + mfmsr r7 /* Save MSR in r7 */ + rlwinm r4,r7,0,17,15 + rlwinm r4,r4,0,28,26 /* Turn off DR bit */ + sync + mtmsr r4 + isync + + /* Get the current enable bit of the L2CR into r4 */ + mfspr r4,L2CR + + /* Tweak some bits */ + rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ + + /* Check to see if we need to flush */ + rlwinm. r4,r4,0,0,0 + beq 2f + + /* Flush the cache. First, read the first 4MB of memory (physical) to + * put new data in the cache. (Actually we only need + * the size of the L2 cache plus the size of the L1 cache, but 4MB will + * cover everything just to be safe). + */ + + /**** Might be a good idea to set L2DO here - to prevent instructions + from getting into the cache. But since we invalidate + the next time we enable the cache it doesn't really matter. + ****/ + + lis r4,0x0002 + mtctr r4 + li r4,0 +1: + lwzx r0,r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + + /* Now, flush the first 4MB of memory */ + lis r4,0x0002 + mtctr r4 + li r4,0 + sync +1: + dcbf r0,r4 + addi r4,r4,32 /* Go to start of next cache line */ + bdnz 1b + +2: + /* Set up the L2CR configuration bits (and switch L2 off) */ + sync + mtspr L2CR,r3 + sync + + /* Before we perform the global invalidation, we must disable dynamic + * power management via HID0[DPM] to work around a processor bug where + * DPM can possibly interfere with the state machine in the processor + * that invalidates the L2 cache tags. + */ + mfspr r8,HID0 /* Save HID0 in r8 */ + rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ + sync + mtspr HID0,r4 /* Disable DPM */ + sync + + /* Perform a global invalidation */ + oris r3,r3,0x0020 + sync + mtspr L2CR,r3 + sync + isync /* For errata */ + + /* Wait for the invalidation to complete */ +3: mfspr r3,L2CR + rlwinm. r4,r3,0,31,31 + bne 3b + + rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ + sync + mtspr L2CR,r3 + sync + + /* Restore HID0[DPM] to whatever it was before */ + sync + mtspr 1008,r8 + sync + + /* See if we need to enable the cache */ + cmplwi r5,0 + beq 4f + + /* Enable the cache */ + oris r3,r3,0x8000 + mtspr L2CR,r3 + sync + + /* Restore MSR (restores EE and DR bits to original state) */ +4: SYNC + mtmsr r7 + isync + blr + +_GLOBAL(_get_L2CR) + /* Return the L2CR contents */ + li r3,0 +BEGIN_FTR_SECTION + mfspr r3,L2CR +END_FTR_SECTION_IFSET(CPU_FTR_L2CR) + blr + +/* --- End of PowerLogix code --- + */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c --- v2.4.9/linux/arch/ppc/kernel/m8260_setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/m8260_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.m8260_setup.c 1.20 07/18/01 22:56:39 paulus + * BK Id: SCCS/s.m8260_setup.c 1.24 08/20/01 15:25:16 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -52,17 +52,6 @@ unsigned long m8260_get_rtc_time(void); void m8260_calibrate_decr(void); -#if 0 -extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_pretranslate(unsigned char scancode, char raw_mode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); -extern void mackbd_init_hw(void); -#endif - extern unsigned long loops_per_jiffy; unsigned char __res[sizeof(bd_t)]; @@ -72,10 +61,6 @@ extern unsigned long find_available_memory(void); extern void m8260_cpm_reset(void); -void __init adbdev_init(void) -{ -} - void __init m8260_setup_arch(void) { @@ -102,7 +87,7 @@ bd_t *binfo = (bd_t *)__res; int freq, divisor; - freq = (binfo->bi_busfreq * 1000000); + freq = binfo->bi_busfreq; divisor = 4; tb_ticks_per_jiffy = freq / HZ / divisor; tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000); @@ -111,7 +96,8 @@ /* The 8260 has an internal 1-second timer update register that * we should use for this purpose. */ -static uint rtc_time; +static uint rtc_time; + static int m8260_set_rtc_time(unsigned long time) { @@ -145,7 +131,7 @@ startaddr = simple_strtoul(&cmd[10], NULL, 0); } - m8260_gorom((uint)__pa(__res), startaddr); + m8260_gorom((unsigned int)__pa(__res), startaddr); } void @@ -171,9 +157,9 @@ len += sprintf(len+buffer,"core clock\t: %d MHz\n" "CPM clock\t: %d MHz\n" "bus clock\t: %d MHz\n", - bp->bi_intfreq /*/ 1000000*/, - bp->bi_cpmfreq /*/ 1000000*/, - bp->bi_busfreq /*/ 1000000*/); + bp->bi_intfreq / 1000000, + bp->bi_cpmfreq / 1000000, + bp->bi_busfreq / 1000000); return len; } @@ -219,9 +205,21 @@ return binfo->bi_memsize; } +/* Map the IMMR, plus anything else we can cover + * in that upper space according to the memory controller + * chip select mapping. Grab another bunch of space + * below that for stuff we can't cover in the upper. + */ +static void __init +m8260_map_io(void) +{ + io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); + io_block_mapping(0xe0000000, 0xe0000000, 0x10000000, _PAGE_IO); +} + void __init -m8260_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { if ( r3 ) @@ -261,6 +259,7 @@ ppc_md.calibrate_decr = m8260_calibrate_decr; ppc_md.find_end_of_memory = m8260_find_end_of_memory; + ppc_md.setup_io_mappings = m8260_map_io; ppc_md.kbd_setkeycode = NULL; ppc_md.kbd_getkeycode = NULL; @@ -273,51 +272,11 @@ #endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = m8xx_ide_insw; - ppc_ide_md.outsw = m8xx_ide_outsw; ppc_ide_md.default_irq = m8xx_ide_default_irq; ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; ppc_ide_md.ide_request_irq = m8xx_ide_request_irq; - - ppc_ide_md.io_base = _IO_BASE; #endif -} - -/* - * Copied from prom.c so I don't have include all of that crap. - * -- Dan - * - * prom_init() is called very early on, before the kernel text - * and data have been mapped to KERNELBASE. At this point the code - * is running at whatever address it has been loaded at, so - * references to extern and static variables must be relocated - * explicitly. The procedure reloc_offset() returns the address - * we're currently running at minus the address we were linked at. - * (Note that strings count as static variables.) - */ -extern unsigned long reloc_offset(void); -#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) - -__init -unsigned long -prom_init(uint r3, uint r4, uint r5, uint r6) -{ - unsigned long offset = reloc_offset(); - unsigned long phys; - extern char __bss_start, _end; - - /* First zero the BSS -- use memset, some arches don't have - * caches on yet */ - memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); - - /* Default */ - phys = offset + KERNELBASE; - - /* We are done. - */ - return phys; } /* Mainly for ksyms. diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c --- v2.4.9/linux/arch/ppc/kernel/m8xx_setup.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/m8xx_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.m8xx_setup.c 1.23 07/18/01 22:56:39 paulus + * BK Id: SCCS/s.m8xx_setup.c 1.27 08/20/01 15:25:16 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -358,26 +358,6 @@ } #endif -void -m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - ide_insw(port, buf, ns); -#else - _insw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -#endif -} - -void -m8xx_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - ide_outsw(port, buf, ns); -#else - _outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -#endif -} - int m8xx_ide_default_irq(ide_ioreg_t base) { @@ -479,7 +459,7 @@ # endif /* CONFIG_SPD823TS, CONFIG_IVMS8 */ for (i = 0; i < IDE_NR_PORTS; ++i) { - *p++ = base + ioport_dsc[data_port].reg_off[i]; + *p++ = base + ioport_dsc[data_port].reg_off[i] - _IO_BASE; } if (irq) { @@ -595,9 +575,45 @@ return binfo->bi_memsize; } +/* + * Now map in some of the I/O space that is generically needed + * or shared with multiple devices. + * All of this fits into the same 4Mbyte region, so it only + * requires one page table page. (or at least it used to -- paulus) + */ +void __init m8xx_map_io(void) +{ + io_block_mapping(IMAP_ADDR, IMAP_ADDR, IMAP_SIZE, _PAGE_IO); +#ifdef CONFIG_MBX + io_block_mapping(NVRAM_ADDR, NVRAM_ADDR, NVRAM_SIZE, _PAGE_IO); + io_block_mapping(MBX_CSR_ADDR, MBX_CSR_ADDR, MBX_CSR_SIZE, _PAGE_IO); + io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO); + + /* Map some of the PCI/ISA I/O space to get the IDE interface. + */ + io_block_mapping(PCI_ISA_IO_ADDR, PCI_ISA_IO_ADDR, 0x4000, _PAGE_IO); + io_block_mapping(PCI_IDE_ADDR, PCI_IDE_ADDR, 0x4000, _PAGE_IO); +#endif +#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) + io_block_mapping(RPX_CSR_ADDR, RPX_CSR_ADDR, RPX_CSR_SIZE, _PAGE_IO); +#if !defined(CONFIG_PCI) + io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); +#endif +#endif +#ifdef CONFIG_HTDMSOUND + io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO); +#endif +#ifdef CONFIG_FADS + io_block_mapping(BCSR_ADDR, BCSR_ADDR, BCSR_SIZE, _PAGE_IO); +#endif +#ifdef CONFIG_PCI + io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO); +#endif +} + void __init -m8xx_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { if ( r3 ) @@ -641,6 +657,7 @@ ppc_md.calibrate_decr = m8xx_calibrate_decr; ppc_md.find_end_of_memory = m8xx_find_end_of_memory; + ppc_md.setup_io_mappings = m8xx_map_io; ppc_md.kbd_setkeycode = NULL; ppc_md.kbd_getkeycode = NULL; @@ -653,13 +670,8 @@ #endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = m8xx_ide_insw; - ppc_ide_md.outsw = m8xx_ide_outsw; ppc_ide_md.default_irq = m8xx_ide_default_irq; ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; #endif } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.4.9/linux/arch/ppc/kernel/misc.S Sun Aug 12 13:27:58 2001 +++ linux/arch/ppc/kernel/misc.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.misc.S 1.21 07/07/01 17:00:08 paulus + * BK Id: SCCS/s.misc.S 1.28 08/24/01 20:07:37 paulus */ /* * This file contains miscellaneous low-level functions. @@ -22,6 +22,7 @@ #include #include #include +#include #include "ppc_asm.h" .text @@ -49,6 +50,97 @@ mtlr r0 blr +/* + * identify_cpu, + * called with r3 = data offset and r4 = CPU number + * doesn't change r3 + */ +_GLOBAL(identify_cpu) + addis r8,r3,cpu_specs@ha + addi r8,r8,cpu_specs@l + mfpvr r7 +1: + lwz r5,CPU_SPEC_PVR_MASK(r8) + and r5,r5,r7 + lwz r6,CPU_SPEC_PVR_VALUE(r8) + cmplw 0,r6,r5 + beq 1f + addi r8,r8,CPU_SPEC_ENTRY_SIZE + b 1b +1: + addis r6,r3,cur_cpu_spec@ha + addi r6,r6,cur_cpu_spec@l + slwi r4,r4,2 + sub r8,r8,r3 + stwx r8,r4,r6 + blr + +/* + * do_cpu_ftr_fixups - goes through the list of CPU feature fixups + * and writes nop's over sections of code that don't apply for this cpu. + * r3 = data offset (not changed) + */ +_GLOBAL(do_cpu_ftr_fixups) + /* Get CPU 0 features */ + addis r6,r3,cur_cpu_spec@ha + addi r6,r6,cur_cpu_spec@l + lwz r4,0(r6) + add r4,r4,r3 + lwz r4,CPU_SPEC_FEATURES(r4) + + /* Get the fixup table */ + addis r6,r3,__start___ftr_fixup@ha + addi r6,r6,__start___ftr_fixup@l + addis r7,r3,__stop___ftr_fixup@ha + addi r7,r7,__stop___ftr_fixup@l + + /* Do the fixup */ +1: cmplw 0,r6,r7 + bgelr + addi r6,r6,16 + lwz r8,-16(r6) /* mask */ + and r8,r8,r4 + lwz r9,-12(r6) /* value */ + cmplw 0,r8,r9 + beq 1b + lwz r8,-8(r6) /* section begin */ + lwz r9,-4(r6) /* section end */ + subf. r9,r8,r9 + beq 1b + /* write nops over the section of code */ + /* todo: if large section, add a branch at the start of it */ + srwi r9,r9,2 + mtctr r9 + add r8,r8,r3 + lis r0,0x60000000@h /* nop */ +3: stw r0,0(r8) + andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l + beq 2f + dcbst 0,r8 /* suboptimal, but simpler */ + sync + icbi 0,r8 +2: addi r8,r8,4 + bdnz 3b + sync /* additional sync needed on g4 */ + isync + b 1b + +/* + * call_setup_cpu - call the setup_cpu function for this cpu + * r3 = data offset, r24 = cpu number + */ +_GLOBAL(call_setup_cpu) + addis r5,r3,cur_cpu_spec@ha + addi r5,r5,cur_cpu_spec@l + slwi r4,r24,2 + lwzx r5,r4,r5 + add r5,r5,r3 + lwz r6,CPU_SPEC_SETUP(r5) + add r6,r6,r3 + mtctr r6 + mr r3,r24 + bctr + /* void __save_flags_ptr(unsigned long *flags) */ _GLOBAL(__save_flags_ptr) mfmsr r4 @@ -185,7 +277,7 @@ _GLOBAL(_nmask_and_or_msr) mfmsr r0 /* Get current msr */ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */ - or r0,r0,r4 /* Or on the bits in r4 (second parm) */ + or r0,r0,r4 /* Or on the bits in r4 (second parm) */ SYNC /* Some chip revs have problems here... */ mtmsr r0 /* Update machine state */ isync @@ -216,8 +308,7 @@ tlbia sync #ifdef CONFIG_SMP - tlbsync - sync + TLBSYNC li r0,0 stw r0,0(r9) /* clear hash_table_lock */ mtmsr r10 @@ -249,8 +340,7 @@ tlbie r3 sync #ifdef CONFIG_SMP - tlbsync - sync + TLBSYNC li r0,0 stw r0,0(r9) /* clear hash_table_lock */ mtmsr r10 @@ -314,26 +404,70 @@ sync /* additional sync needed on g4 */ isync blr +/* + * Write any modified data cache blocks out to memory. + * Does not invalidate the corresponding cache lines (especially for + * any corresponding instruction cache). + * + * clean_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(clean_dcache_range) + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + +1: dcbst 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbst's to get to ram */ + blr /* - * Like above, but only do the D-cache. + * Write any modified data cache blocks out to memory + * and invalidate the corresponding instruction cache blocks. * * flush_dcache_range(unsigned long start, unsigned long stop) */ _GLOBAL(flush_dcache_range) - li r5,CACHE_LINE_SIZE-1 - andc r3,r3,r5 - subf r4,r3,r4 - add r4,r4,r5 - srwi. r4,r4,LG_CACHE_LINE_SIZE - beqlr - mtctr r4 - -1: dcbst 0,r3 - addi r3,r3,CACHE_LINE_SIZE - bdnz 1b - sync /* wait for dcbst's to get to ram */ - blr + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + +1: dcbf 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbst's to get to ram */ + blr + +/* + * Like above, but invalidate the D-cache. This is used by the 8xx + * to invalidate the cache so the PPC core doesn't get stale data + * from the CPM (no cache snooping here :-). + * + * invalidate_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(invalidate_dcache_range) + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + +1: dcbi 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbi's to get to ram */ + blr /* * Flush a particular page from the data cache to RAM. @@ -481,94 +615,9 @@ blr /* - * Try to acquire a spinlock. - * Only does the stwcx. if the load returned 0 - the Programming - * Environments Manual suggests not doing unnecessary stcwx.'s - * since they may inhibit forward progress by other CPUs in getting - * a lock. - */ -_GLOBAL(__spin_trylock) - mr r4,r3 - eieio /* prevent reordering of stores */ - li r5,-1 - lwarx r3,0,r4 /* fetch old value, establish reservation */ - cmpwi 0,r3,0 /* is it 0? */ - bnelr- /* return failure if not */ - stwcx. r5,0,r4 /* try to update with new value */ - bne- 1f /* if we failed */ - eieio /* prevent reordering of stores */ - blr -1: li r3,1 /* return non-zero for failure */ - blr - -/* - * Atomic add/sub/inc/dec operations - * - * void atomic_add(int c, int *v) - * void atomic_sub(int c, int *v) - * void atomic_inc(int *v) - * void atomic_dec(int *v) - * int atomic_dec_and_test(int *v) - * int atomic_inc_return(int *v) - * int atomic_dec_return(int *v) * void atomic_clear_mask(atomic_t mask, atomic_t *addr) * void atomic_set_mask(atomic_t mask, atomic_t *addr); */ -#if 0 /* now inline - paulus */ -_GLOBAL(atomic_add) -10: lwarx r5,0,r4 /* Fetch old value & reserve */ - add r5,r5,r3 /* Perform 'add' operation */ - stwcx. r5,0,r4 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_add_return) -10: lwarx r5,0,r4 /* Fetch old value & reserve */ - add r5,r5,r3 /* Perform 'add' operation */ - stwcx. r5,0,r4 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - mr r3,r5 - blr -_GLOBAL(atomic_sub) -10: lwarx r5,0,r4 /* Fetch old value & reserve */ - sub r5,r5,r3 /* Perform 'add' operation */ - stwcx. r5,0,r4 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_inc) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - addi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_inc_return) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - addi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - mr r3,r5 /* Return new value */ - blr -_GLOBAL(atomic_dec) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - subi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - blr -_GLOBAL(atomic_dec_return) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - subi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - mr r3,r5 /* Return new value */ - blr -_GLOBAL(atomic_dec_and_test) -10: lwarx r5,0,r3 /* Fetch old value & reserve */ - subi r5,r5,1 /* Perform 'add' operation */ - stwcx. r5,0,r3 /* Update with new value */ - bne- 10b /* Retry if "reservation" (i.e. lock) lost */ - cntlzw r3,r5 - srwi r3,r3,5 - blr -#endif /* 0 */ _GLOBAL(atomic_clear_mask) 10: lwarx r5,0,r4 andc r5,r5,r3 @@ -768,281 +817,7 @@ _GLOBAL(_get_SP) mr r3,r1 /* Close enough */ blr - -#if 0 -/* isn't it just easier to use the mtspr/mfspr inline macros?? --Troy */ -_GLOBAL(_get_THRM1) - mfspr r3,THRM1 - blr - -_GLOBAL(_get_THRM2) - mfspr r3,THRM2 - blr - -_GLOBAL(_get_THRM3) - mfspr r3,THRM3 - blr - -_GLOBAL(_set_THRM1) - mtspr THRM1,r3 - blr - -_GLOBAL(_set_THRM2) - mtspr THRM2,r3 - blr - -_GLOBAL(_set_THRM3) - mtspr THRM3,r3 - blr -#endif - -_GLOBAL(_get_PVR) - mfspr r3,PVR - blr - -#ifdef CONFIG_8xx -_GLOBAL(_get_IMMR) - mfspr r3, 638 - blr -#endif -_GLOBAL(_get_HID0) - mfspr r3,HID0 - blr - -_GLOBAL(_set_HID0) - sync - mtspr HID0, r3 - SYNC /* Handle errata in some cases */ - blr - -_GLOBAL(_get_ICTC) - mfspr r3,ICTC - blr - -_GLOBAL(_set_ICTC) - mtspr ICTC,r3 - blr - -/* - L2CR functions - Copyright © 1997-1998 by PowerLogix R & D, Inc. - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - Thur, Dec. 12, 1998. - - First public release, contributed by PowerLogix. - *********** - Sat, Aug. 7, 1999. - - Terry: Made sure code disabled interrupts before running. (Previously - it was assumed interrupts were already disabled). - - Terry: Updated for tentative G4 support. 4MB of memory is now flushed - instead of 2MB. (Prob. only 3 is necessary). - - Terry: Updated for workaround to HID0[DPM] processor bug - during global invalidates. - *********** - Thu, July 13, 2000. - - Terry: Added isync to correct for an errata. - - Author: Terry Greeniaus (tgree@phys.ualberta.ca) - Please e-mail updates to this file to me, thanks! -*/ -/* Usage: - - When setting the L2CR register, you must do a few special - things. If you are enabling the cache, you must perform a - global invalidate. If you are disabling the cache, you must - flush the cache contents first. This routine takes care of - doing these things. When first enabling the cache, make sure - you pass in the L2CR you want, as well as passing in the - global invalidate bit set. A global invalidate will only be - performed if the L2I bit is set in applyThis. When enabling - the cache, you should also set the L2E bit in applyThis. If - you want to modify the L2CR contents after the cache has been - enabled, the recommended procedure is to first call - __setL2CR(0) to disable the cache and then call it again with - the new values for L2CR. Examples: - - _setL2CR(0) - disables the cache - _setL2CR(0xB3A04000) - enables my G3 upgrade card: - - L2E set to turn on the cache - - L2SIZ set to 1MB - - L2CLK set to 1:1 - - L2RAM set to pipelined synchronous late-write - - L2I set to perform a global invalidation - - L2OH set to 0.5 nS - - L2DF set because this upgrade card - requires it - - A similar call should work for your card. You need to know - the correct setting for your card and then place them in the - fields I have outlined above. Other fields support optional - features, such as L2DO which caches only data, or L2TS which - causes cache pushes from the L1 cache to go to the L2 cache - instead of to main memory. -*/ -/* - * Summary: this procedure ignores the L2I bit in the value passed in, - * flushes the cache if it was already enabled, always invalidates the - * cache, then enables the cache if the L2E bit is set in the value - * passed in. - * -- paulus. - */ -_GLOBAL(_set_L2CR) - /* Make sure this is a 750 or 7400 chip */ - mfspr r4,PVR - rlwinm r4,r4,16,16,31 - cmpwi r4,0x0008 - cmpwi cr1,r4,0x000c - cror 2,2,4*cr1+2 - bne 99f - - /* Turn off interrupts and data relocation. */ - mfmsr r7 /* Save MSR in r7 */ - rlwinm r4,r7,0,17,15 - rlwinm r4,r4,0,28,26 /* Turn off DR bit */ - sync - mtmsr r4 - isync - - /* Get the current enable bit of the L2CR into r4 */ - mfspr r4,L2CR - - /* Tweak some bits */ - rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ - rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ - rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ - - /* Check to see if we need to flush */ - rlwinm. r4,r4,0,0,0 - beq 2f - - /* Flush the cache. First, read the first 4MB of memory (physical) to - * put new data in the cache. (Actually we only need - * the size of the L2 cache plus the size of the L1 cache, but 4MB will - * cover everything just to be safe). - */ - - /**** Might be a good idea to set L2DO here - to prevent instructions - from getting into the cache. But since we invalidate - the next time we enable the cache it doesn't really matter. - ****/ - - lis r4,0x0002 - mtctr r4 - li r4,0 -1: - lwzx r0,r0,r4 - addi r4,r4,32 /* Go to start of next cache line */ - bdnz 1b - - /* Now, flush the first 4MB of memory */ - lis r4,0x0002 - mtctr r4 - li r4,0 - sync -1: - dcbf r0,r4 - addi r4,r4,32 /* Go to start of next cache line */ - bdnz 1b - -2: - /* Set up the L2CR configuration bits (and switch L2 off) */ - sync - mtspr L2CR,r3 - sync - - /* Before we perform the global invalidation, we must disable dynamic - * power management via HID0[DPM] to work around a processor bug where - * DPM can possibly interfere with the state machine in the processor - * that invalidates the L2 cache tags. - */ - mfspr r8,HID0 /* Save HID0 in r8 */ - rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ - sync - mtspr HID0,r4 /* Disable DPM */ - sync - - /* Perform a global invalidation */ - oris r3,r3,0x0020 - sync - mtspr L2CR,r3 - sync - isync /* For errata */ - - /* Wait for the invalidation to complete */ -3: mfspr r3,L2CR - rlwinm. r4,r3,0,31,31 - bne 3b - - rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ - sync - mtspr L2CR,r3 - sync - - /* Restore HID0[DPM] to whatever it was before */ - sync - mtspr 1008,r8 - sync - - /* See if we need to enable the cache */ - cmplwi r5,0 - beq 4f - - /* Enable the cache */ - oris r3,r3,0x8000 - mtspr L2CR,r3 - sync - - /* Restore MSR (restores EE and DR bits to original state) */ -4: SYNC - mtmsr r7 - isync - blr - -99: li r3,-1 - blr - -_GLOBAL(_get_L2CR) - /* Make sure this is a 750 chip */ - mfspr r3,PVR - srwi r3,r3,16 - cmpwi r3,0x0008 - cmpwi cr1,r3,0x000c - li r3,0 - cror 2,2,4*cr1+2 - bnelr - /* Return the L2CR contents */ - mfspr r3,L2CR - blr - -/* --- End of PowerLogix code --- - */ - -/* -_GLOBAL(_get_L2CR) - mfspr r3,L2CR - blr - -_GLOBAL(_set_L2CR) - mtspr L2CR,r3 - blr - -*/ - /* * These are used in the alignment trap handler when emulating * single-precision loads and stores. @@ -1099,7 +874,7 @@ mr r3,r4 /* load arg and call fn */ blrl li r0,__NR_exit /* exit after child exits */ - li r3,0 + li r3,0 sc /* @@ -1279,7 +1054,7 @@ .long sys_setfsuid .long sys_setfsgid .long sys_llseek /* 140 */ - .long sys_getdents + .long sys_getdents .long ppc_select .long sys_flock .long sys_msync diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c --- v2.4.9/linux/arch/ppc/kernel/mk_defs.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/mk_defs.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.mk_defs.c 1.8 06/28/01 15:50:16 paulus + * BK Id: SCCS/s.mk_defs.c 1.11 08/19/01 22:43:23 paulus */ /* * This program is used to generate definitions needed by @@ -26,6 +26,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n#define\t" #sym "\t%0" : : "i" (val)) @@ -118,5 +119,14 @@ DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(CLONE_VM, CLONE_VM); DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); + + /* About the CPU features table */ + DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); + DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); + DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); + DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); + DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); + + DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); return 0; } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c --- v2.4.9/linux/arch/ppc/kernel/oak_setup.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/oak_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.oak_setup.c 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.oak_setup.c 1.8 08/15/01 21:48:38 paulus */ /* * @@ -74,8 +74,8 @@ * */ void __init -oak_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { /* * If we were passed in a board information, copy it into the diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c --- v2.4.9/linux/arch/ppc/kernel/open_pic.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/open_pic.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.open_pic.c 1.20 05/17/01 18:14:21 cort + * BK Id: SCCS/s.open_pic.c 1.26 08/20/01 22:33:28 paulus */ /* * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling @@ -17,11 +17,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "local_irq.h" #include "open_pic.h" @@ -47,8 +49,6 @@ /* Global Operations */ static void openpic_disable_8259_pass_through(void); -static u_int openpic_irq(void); -static void openpic_eoi(void); static void openpic_set_priority(u_int pri); static void openpic_set_spurious(u_int vector); @@ -73,8 +73,8 @@ * These functions are not used but the code is kept here * for completeness and future reference. */ -#ifdef notused static void openpic_reset(void); +#ifdef notused static void openpic_enable_8259_pass_through(void); static u_int openpic_get_priority(void); static u_int openpic_get_spurious(void); @@ -412,13 +412,16 @@ #endif } -#ifdef notused static void openpic_reset(void) { openpic_setfield(&OpenPIC->Global.Global_Configuration0, OPENPIC_CONFIG_RESET); + while (openpic_readfield(&OpenPIC->Global.Global_Configuration0, + OPENPIC_CONFIG_RESET)) + mb(); } +#ifdef notused static void openpic_enable_8259_pass_through(void) { openpic_clearfield(&OpenPIC->Global.Global_Configuration0, @@ -435,7 +438,7 @@ /* * Find out the current interrupt */ -static u_int openpic_irq(void) +u_int openpic_irq(void) { u_int vec; DECL_THIS_CPU; @@ -446,7 +449,7 @@ return vec; } -static void openpic_eoi(void) +void openpic_eoi(void) { DECL_THIS_CPU; @@ -518,6 +521,8 @@ physmask(cpumask)); } +static spinlock_t openpic_setup_lock = SPIN_LOCK_UNLOCKED; + #ifdef CONFIG_SMP /* * Initialize an interprocessor interrupt (and disable it) @@ -583,7 +588,6 @@ * Get IPI's working and start taking interrupts. * -- Cort */ -static spinlock_t openpic_setup_lock __initdata = SPIN_LOCK_UNLOCKED; void __init do_openpic_setup_cpu(void) { @@ -802,11 +806,87 @@ #endif openpic_eoi(); } - if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) { + if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) irq = -1; - /* That's not SMP safe ... but who cares ? */ - ppc_spurious_interrupts++; - } return irq; } +#ifdef CONFIG_SMP +void +smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) +{ + /* make sure we're sending something that translates to an IPI */ + if (msg > 0x3) { + printk("SMP %d: smp_message_pass: unknown msg %d\n", + smp_processor_id(), msg); + return; + } + switch (target) { + case MSG_ALL: + openpic_cause_IPI(msg, 0xffffffff); + break; + case MSG_ALL_BUT_SELF: + openpic_cause_IPI(msg, + 0xffffffff & ~(1 << smp_processor_id())); + break; + default: + openpic_cause_IPI(msg, 1<Processor[i].Current_Task_Priority); + openpic_writefield(&OpenPIC->Processor[i].Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf); + } + + for (i=0; iGlobal.IPI_Vector_Priority(i)); + for (i=0; iSource[i].Vector_Priority) + & ~OPENPIC_ACTIVITY; + save_irq_src_dest[i] = openpic_read(&OpenPIC->Source[i].Destination); + } + spin_unlock_irqrestore(&openpic_setup_lock, flags); +} + +void __pmac +openpic_sleep_restore_intrs(void) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&openpic_setup_lock, flags); + + openpic_reset(); + + for (i=0; iGlobal.IPI_Vector_Priority(i), save_ipi_vp[i]); + for (i=0; iSource[i].Vector_Priority, save_irq_src_vp[i]); + openpic_write(&OpenPIC->Source[i].Destination, save_irq_src_dest[i]); + } + openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset); + openpic_disable_8259_pass_through(); + for (i=0; iProcessor[i].Current_Task_Priority, save_cpu_task_pri[i]); + + spin_unlock_irqrestore(&openpic_setup_lock, flags); +} +#endif /* CONFIG_PMAC_PBOOK */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h --- v2.4.9/linux/arch/ppc/kernel/open_pic.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/open_pic.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.open_pic.h 1.8 05/17/01 18:14:21 cort + * BK Id: SCCS/s.open_pic.h 1.12 08/20/01 22:33:28 paulus */ /* * arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling @@ -19,6 +19,14 @@ #define OPENPIC_SIZE 0x40000 +/* + * Non-offset'ed vector numbers + */ + +#define OPENPIC_VEC_TIMER 64 /* and up */ +#define OPENPIC_VEC_IPI 72 /* and up */ +#define OPENPIC_VEC_SPURIOUS 127 + /* OpenPIC IRQ controller structure */ extern struct hw_interrupt_type open_pic; @@ -33,16 +41,28 @@ /* Exported functions */ extern void openpic_init(int, int, unsigned char *, int); +extern u_int openpic_irq(void); +extern void openpic_eoi(void); extern void openpic_request_IPIs(void); extern void do_openpic_setup_cpu(void); extern int openpic_get_irq(struct pt_regs *regs); extern void openpic_init_processor(u_int cpumask); extern void openpic_setup_ISU(int isu_num, unsigned long addr); extern void openpic_cause_IPI(u_int ipi, u_int cpumask); +extern void smp_openpic_message_pass(int target, int msg, unsigned long data, + int wait); extern inline int openpic_to_irq(int irq) { - return irq += NUM_8259_INTERRUPTS; + /* IRQ 0 usually means 'disabled'.. don't mess with it + * exceptions to this (sandpoint maybe?) + * shouldn't use openpic_to_irq + */ + if (irq != 0){ + return irq += NUM_8259_INTERRUPTS; + } else { + return 0; + } } /*extern int open_pic_irq_offset;*/ #endif /* _PPC_KERNEL_OPEN_PIC_H */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/open_pic_defs.h linux/arch/ppc/kernel/open_pic_defs.h --- v2.4.9/linux/arch/ppc/kernel/open_pic_defs.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/open_pic_defs.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.open_pic_defs.h 1.7 05/17/01 18:14:21 cort + * BK Id: SCCS/s.open_pic_defs.h 1.8 08/20/01 22:33:28 paulus */ /* * linux/openpic.h -- OpenPIC definitions @@ -44,14 +44,6 @@ #define OPENPIC_NUM_PRI 16 #define OPENPIC_NUM_VECTORS 256 - - /* - * Non-offset'ed vector numbers - */ - -#define OPENPIC_VEC_TIMER 64 /* and up */ -#define OPENPIC_VEC_IPI 72 /* and up */ -#define OPENPIC_VEC_SPURIOUS 127 /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_nvram.c linux/arch/ppc/kernel/pmac_nvram.c --- v2.4.9/linux/arch/ppc/kernel/pmac_nvram.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_nvram.c Tue Aug 28 06:58:33 2001 @@ -1,10 +1,11 @@ /* - * BK Id: SCCS/s.pmac_nvram.c 1.10 08/08/01 16:23:35 paulus + * BK Id: SCCS/s.pmac_nvram.c 1.13 08/19/01 22:23:04 paulus */ /* * Miscellaneous procedures for dealing with the PowerMac hardware. */ #include +#include #include #include #include diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c --- v2.4.9/linux/arch/ppc/kernel/pmac_pci.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_pci.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pci.c 1.22 08/08/01 16:35:43 paulus + * BK Id: SCCS/s.pmac_pci.c 1.25 08/19/01 22:23:04 paulus */ /* * Support for PCI bridges found on Power Macintoshes. @@ -528,6 +528,7 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) { struct device_node* node; + int updatecfg = 0; node = pci_device_to_OF_node(dev); @@ -538,14 +539,40 @@ && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node) return -EINVAL; - /* Firewire was disabled after PCI probe, the driver is claiming it, - * so we must re-enable it now, at least until the driver can do it - * itself. + /* Firewire & GMAC were disabled after PCI probe, the driver is + * claiming them, we must re-enable them now. */ if (node && !strcmp(node->name, "firewire") && - device_is_compatible(node, "pci106b,18")) { + (device_is_compatible(node, "pci106b,18") || + device_is_compatible(node, "pci106b,30"))) { feature_set_firewire_cable_power(node, 1); feature_set_firewire_power(node, 1); + updatecfg = 1; + } + if (node && !strcmp(node->name, "ethernet") && + device_is_compatible(node, "gmac")) { + feature_set_gmac_power(node, 1); + updatecfg = 1; + } + + if (updatecfg) { + u16 cmd; + + /* + * Make sure PCI is correctly configured + * + * We use old pci_bios versions of the function since, by + * default, gmac is not powered up, and so will be absent + * from the kernel initial PCI lookup. + * + * Should be replaced by 2.4 new PCI mecanisms and really + * regiser the device. + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; + pci_write_config_word(dev, PCI_COMMAND, cmd); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); } return 0; @@ -580,7 +607,8 @@ nd = find_devices("firewire"); while (nd) { - if (nd->parent && device_is_compatible(nd, "pci106b,18") + if (nd->parent && (device_is_compatible(nd, "pci106b,18") || + device_is_compatible(nd, "pci106b,30")) && device_is_compatible(nd->parent, "uni-north")) { feature_set_firewire_power(nd, 0); feature_set_firewire_cable_power(nd, 0); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c --- v2.4.9/linux/arch/ppc/kernel/pmac_pic.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pmac_pic.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pic.c 1.14 05/17/01 18:14:21 cort + * BK Id: SCCS/s.pmac_pic.c 1.18 08/19/01 22:23:04 paulus */ #include #include @@ -35,7 +35,6 @@ static int max_irqs; static int max_real_irqs; -static int pmac_has_openpic; spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED; @@ -291,17 +290,16 @@ * controller. If we find this second ohare, set it up and fix the * interrupt value in the device tree for the ethernet chip. */ -static void __init enable_second_ohare(void) +static int __init enable_second_ohare(void) { unsigned char bus, devfn; unsigned short cmd; unsigned long addr; - int second_irq; struct device_node *irqctrler = find_devices("pci106b,7"); struct device_node *ether; if (irqctrler == NULL || irqctrler->n_addrs <= 0) - return; + return -1; addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); max_irqs = 64; @@ -317,11 +315,6 @@ } } - second_irq = irqctrler->intrs[0].line; - printk(KERN_INFO "irq: secondary controller on irq %d\n", second_irq); - request_irq(second_irq, gatwick_action, SA_INTERRUPT, - "interrupt cascade", 0 ); - /* Fix interrupt for the modem/ethernet combo controller. The number in the device tree (27) is bogus (correct for the ethernet-only board but not the combo ethernet/modem board). @@ -333,6 +326,9 @@ printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", ether->intrs[0].line); } + + /* Return the interrupt number of the cascade */ + return irqctrler->intrs[0].line; } void __init @@ -341,8 +337,8 @@ int i; struct device_node *irqctrler; unsigned long addr; - int second_irq = -999; - + int irq_cascade = -1; + /* We first try to detect Apple's new Core99 chipset, since mac-io * is quite different on those machines and contains an IBM MPIC2. */ @@ -368,7 +364,6 @@ OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, irqctrler->addrs[0].size); openpic_init(1, 0, 0, nmi_irq); - pmac_has_openpic = 1; #ifdef CONFIG_XMON if (nmi_irq >= 0) request_irq(nmi_irq, xmon_irq, 0, @@ -418,6 +413,9 @@ for (i = 2; i < 4; ++i) pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) (addr + (4 - i) * 0x10); + irq_cascade = irqctrler->intrs[0].line; + if (device_is_compatible(irqctrler, "gatwick")) + pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); } } else { /* older powermacs have a GC (grand central) or ohare at @@ -430,23 +428,20 @@ ohare chip, on the combo ethernet/modem card */ if (machine_is_compatible("AAPL,3400/2400") || machine_is_compatible("AAPL,3500")) - enable_second_ohare(); + irq_cascade = enable_second_ohare(); /* disable all interrupts in all controllers */ for (i = 0; i * 32 < max_irqs; ++i) out_le32(&pmac_irq_hw[i]->enable, 0); /* get interrupt line of secondary interrupt controller */ - if (irqctrler) { - second_irq = irqctrler->intrs[0].line; + if (irq_cascade >= 0) { printk(KERN_INFO "irq: secondary controller on irq %d\n", - (int)second_irq); - if (device_is_compatible(irqctrler, "gatwick")) - pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); + (int)irq_cascade); for ( i = max_real_irqs ; i < max_irqs ; i++ ) irq_desc[i].handler = &gatwick_pic; - request_irq( second_irq, gatwick_action, SA_INTERRUPT, - "gatwick cascade", 0 ); + request_irq( irq_cascade, gatwick_action, SA_INTERRUPT, + "cascade", 0 ); } printk("System has %d possible interrupts\n", max_irqs); if (max_irqs != max_real_irqs) @@ -467,14 +462,15 @@ */ unsigned int sleep_save_mask[2]; -void -sleep_save_intrs(int viaint) +void __pmac +pmac_sleep_save_intrs(int viaint) { sleep_save_mask[0] = ppc_cached_irq_mask[0]; sleep_save_mask[1] = ppc_cached_irq_mask[1]; ppc_cached_irq_mask[0] = 0; ppc_cached_irq_mask[1] = 0; - set_bit(viaint, ppc_cached_irq_mask); + if (viaint > 0) + set_bit(viaint, ppc_cached_irq_mask); out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]); if (max_real_irqs > 32) out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]); @@ -484,8 +480,8 @@ (void)in_le32(&pmac_irq_hw[0]->enable); } -void -sleep_restore_intrs(void) +void __pmac +pmac_sleep_restore_intrs(void) { int i; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_pic.h linux/arch/ppc/kernel/pmac_pic.h --- v2.4.9/linux/arch/ppc/kernel/pmac_pic.h Mon May 21 17:04:47 2001 +++ linux/arch/ppc/kernel/pmac_pic.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_pic.h 1.5 05/17/01 18:14:21 cort + * BK Id: SCCS/s.pmac_pic.h 1.9 08/19/01 22:23:04 paulus */ #ifndef _PPC_KERNEL_PMAC_PIC_H #define _PPC_KERNEL_PMAC_PIC_H @@ -10,6 +10,5 @@ void pmac_pic_init(void); int pmac_get_irq(struct pt_regs *regs); -void pmac_post_irq(int); #endif /* _PPC_KERNEL_PMAC_PIC_H */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c --- v2.4.9/linux/arch/ppc/kernel/pmac_setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_setup.c 1.24 07/06/01 14:49:51 trini + * BK Id: SCCS/s.pmac_setup.c 1.35 08/20/01 22:37:37 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -65,6 +65,8 @@ #include #include #include +#include +#include #include #include "local_irq.h" @@ -133,13 +135,16 @@ sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; #ifdef CONFIG_SMP +extern struct smp_ops_t psurge_smp_ops; +extern struct smp_ops_t core99_smp_ops; + volatile static long int core99_l2_cache; -void __pmac +void __init core99_init_l2(void) { int cpu = smp_processor_id(); - if ( (_get_PVR() >> 16) != 8 && (_get_PVR() >> 16) != 12 ) + if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)) return; if (cpu == 0){ @@ -277,6 +282,9 @@ { struct device_node *cpu; int *fp; + unsigned long pvr; + + pvr = PVR_VER(mfspr(PVR)); /* Set loops_per_jiffy to a half-way reasonable value, for use until calibrate_delay gets called. */ @@ -284,18 +292,12 @@ if (cpu != 0) { fp = (int *) get_property(cpu, "clock-frequency", NULL); if (fp != 0) { - switch (_get_PVR() >> 16) { - case 4: /* 604 */ - case 8: /* G3 */ - case 9: /* 604e */ - case 10: /* mach V (604ev5) */ - case 12: /* G4 */ - case 20: /* 620 */ + if (pvr == 4 || pvr >= 8) + /* 604, G3, G4 etc. */ loops_per_jiffy = *fp / HZ; - break; - default: /* 601, 603, etc. */ + else + /* 601, 603, etc. */ loops_per_jiffy = *fp / (2*HZ); - } } else loops_per_jiffy = 50000000 / HZ; } @@ -303,14 +305,13 @@ /* this area has the CPU identification register and some registers used by smp boards */ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); - __ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY)); ohare_init(); /* Lookup PCI hosts */ pmac_find_bridges(); /* Checks "l2cr-value" property in the registry */ - if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) { + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) { struct device_node *np = find_devices("cpus"); if (np == 0) np = find_type_devices("cpu"); @@ -342,9 +343,19 @@ #ifdef CONFIG_ADB_CUDA find_via_cuda(); +#else + if (find_devices("via-cuda")) { + printk("WARNING ! Your machine is Cuda based but your kernel\n"); + printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); + } #endif #ifdef CONFIG_ADB_PMU find_via_pmu(); +#else + if (find_devices("via-pmu")) { + printk("WARNING ! Your machine is PMU based but your kernel\n"); + printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); + } #endif #ifdef CONFIG_NVRAM pmac_nvram_init(); @@ -361,6 +372,14 @@ else #endif ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); + +#ifdef CONFIG_SMP + /* Check for Core99 */ + if (find_devices("uni-n")) + ppc_md.smp_ops = &core99_smp_ops; + else + ppc_md.smp_ops = &psurge_smp_ops; +#endif /* CONFIG_SMP */ } static void __init ohare_init(void) @@ -475,9 +494,11 @@ static int found_boot = 0; char *p; - /* Do nothing if the root has been set already. */ + /* Do nothing if the root has been mounted already. */ + if (init_task.fs->rootmnt != NULL) + return; if ((goodness <= current_root_goodness) && - (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))) + (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))) return; p = strstr(saved_command_line, "root="); if (p != NULL && (p == saved_command_line || p[-1] == ' ')) @@ -563,41 +584,7 @@ /* * IDE stuff. */ -void __pmac -pmac_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - _insw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -} - -void __pmac -pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - _outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns); -} - -int __pmac -pmac_ide_default_irq(ide_ioreg_t base) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - extern int pmac_ide_get_irq(ide_ioreg_t base); - return pmac_ide_get_irq(base); -#else - return 0; -#endif -} - -ide_ioreg_t __pmac -pmac_ide_default_io_base(int index) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - extern ide_ioreg_t pmac_ide_get_base(int index); - return pmac_ide_get_base(index); -#else - return 0; -#endif -} - -int __pmac +static int __pmac pmac_ide_check_region(ide_ioreg_t from, unsigned int extent) { /* @@ -606,11 +593,11 @@ * register, it should be OK. */ if (from < ~_IO_BASE) - return 0; - return check_region(from, extent); + return check_region(from, extent); + return 0; } -void __pmac +static void __pmac pmac_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) @@ -619,7 +606,7 @@ request_region(from, extent, name); } -void __pmac +static void __pmac pmac_ide_release_region(ide_ioreg_t from, unsigned int extent) { @@ -627,21 +614,24 @@ release_region(from, extent); } -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -/* This is declared in drivers/block/ide-pmac.c */ -void __pmac -pmac_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq); -#else /* - * This registers the standard ports for this architecture with the IDE - * driver. + * This is only used if we have a PCI IDE controller, not + * for the IDE controller in the ohare/paddington/heathrow/keylargo. */ -void __pmac -pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) +static void __pmac +pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) { + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; } #endif -#endif /* * Read in a property describing some pieces of memory. @@ -728,39 +718,8 @@ } void __init -pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +select_adb_keyboard(void) { - /* isa_io_base gets set in pmac_find_bridges */ - isa_mem_base = PMAC_ISA_MEM_BASE; - pci_dram_offset = PMAC_PCI_DRAM_OFFSET; - ISA_DMA_THRESHOLD = ~0L; - DMA_MODE_READ = 1; - DMA_MODE_WRITE = 2; - - ppc_md.setup_arch = pmac_setup_arch; - ppc_md.setup_residual = NULL; - ppc_md.get_cpuinfo = pmac_get_cpuinfo; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = pmac_pic_init; - ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ - ppc_md.init = pmac_init2; - - ppc_md.pcibios_fixup = pmac_pcibios_fixup; - ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; - ppc_md.pcibios_after_init = pmac_pcibios_after_init; - - ppc_md.restart = pmac_restart; - ppc_md.power_off = pmac_power_off; - ppc_md.halt = pmac_halt; - - ppc_md.time_init = pmac_time_init; - ppc_md.set_rtc_time = pmac_set_rtc_time; - ppc_md.get_rtc_time = pmac_get_rtc_time; - ppc_md.calibrate_decr = pmac_calibrate_decr; - - ppc_md.find_end_of_memory = pmac_find_end_of_memory; - #ifdef CONFIG_VT #ifdef CONFIG_INPUT ppc_md.kbd_init_hw = mac_hid_init_hw; @@ -768,6 +727,8 @@ ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up; ppc_md.kbd_setkeycode = 0; ppc_md.kbd_getkeycode = 0; + ppc_md.kbd_leds = 0; + ppc_md.kbd_rate_fn = 0; #ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAC_ADBKEYCODES if (!keyboard_sends_linux_keycodes) { @@ -786,6 +747,7 @@ ppc_md.kbd_translate = mackbd_translate; ppc_md.kbd_unexpected_up = mackbd_unexpected_up; ppc_md.kbd_leds = mackbd_leds; + ppc_md.kbd_rate_fn = NULL; ppc_md.kbd_init_hw = mackbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; @@ -793,21 +755,55 @@ #endif /* CONFIG_MAGIC_SYSRQ */ #endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */ #endif /* CONFIG_VT */ +} + +void __init +pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + /* isa_io_base gets set in pmac_find_bridges */ + isa_mem_base = PMAC_ISA_MEM_BASE; + pci_dram_offset = PMAC_PCI_DRAM_OFFSET; + ISA_DMA_THRESHOLD = ~0L; + DMA_MODE_READ = 1; + DMA_MODE_WRITE = 2; + + ppc_md.setup_arch = pmac_setup_arch; + ppc_md.setup_residual = NULL; + ppc_md.get_cpuinfo = pmac_get_cpuinfo; + ppc_md.irq_cannonicalize = NULL; + ppc_md.init_IRQ = pmac_pic_init; + ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ + ppc_md.init = pmac_init2; + + ppc_md.pcibios_fixup = pmac_pcibios_fixup; + ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; + ppc_md.pcibios_after_init = pmac_pcibios_after_init; + + ppc_md.restart = pmac_restart; + ppc_md.power_off = pmac_power_off; + ppc_md.halt = pmac_halt; + + ppc_md.time_init = pmac_time_init; + ppc_md.set_rtc_time = pmac_set_rtc_time; + ppc_md.get_rtc_time = pmac_get_rtc_time; + ppc_md.calibrate_decr = pmac_calibrate_decr; + + ppc_md.find_end_of_memory = pmac_find_end_of_memory; + + select_adb_keyboard(); #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - ppc_ide_md.insw = pmac_ide_insw; - ppc_ide_md.outsw = pmac_ide_outsw; - ppc_ide_md.default_irq = pmac_ide_default_irq; - ppc_ide_md.default_io_base = pmac_ide_default_io_base; ppc_ide_md.ide_check_region = pmac_ide_check_region; ppc_ide_md.ide_request_region = pmac_ide_request_region; ppc_ide_md.ide_release_region = pmac_ide_release_region; - ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid; ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; #endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ + #ifdef CONFIG_BOOTX_TEXT ppc_md.progress = pmac_progress; #endif /* CONFIG_BOOTX_TEXT */ + if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); } @@ -821,7 +817,7 @@ { if (disp_bi == 0) return; - prom_drawstring(s); - prom_drawchar('\n'); + btext_drawstring(s); + btext_drawchar('\n'); } #endif /* CONFIG_BOOTX_TEXT */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_smp.c linux/arch/ppc/kernel/pmac_smp.c --- v2.4.9/linux/arch/ppc/kernel/pmac_smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/pmac_smp.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,488 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * SMP support for power macintosh. + * + * We support both the old "powersurge" SMP architecture + * and the current Core99 (G4 PowerMac) machines. + * + * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) + * and Ben Herrenschmidt . + * + * Support for DayStar quad CPU cards + * Copyright (C) XLR8, Inc. 1994-2000 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open_pic.h" + +/* + * Powersurge (old powermac SMP) support. + */ + +extern void __secondary_start_psurge(void); +extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ +extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ + +/* Addresses for powersurge registers */ +#define HAMMERHEAD_BASE 0xf8000000 +#define HHEAD_CONFIG 0x90 +#define HHEAD_SEC_INTR 0xc0 + +/* register for interrupting the primary processor on the powersurge */ +/* N.B. this is actually the ethernet ROM! */ +#define PSURGE_PRI_INTR 0xf3019000 + +/* register for storing the start address for the secondary processor */ +/* N.B. this is the PCI config space address register for the 1st bridge */ +#define PSURGE_START 0xf2800000 + +/* Daystar/XLR8 4-CPU card */ +#define PSURGE_QUAD_REG_ADDR 0xf8800000 + +#define PSURGE_QUAD_IRQ_SET 0 +#define PSURGE_QUAD_IRQ_CLR 1 +#define PSURGE_QUAD_IRQ_PRIMARY 2 +#define PSURGE_QUAD_CKSTOP_CTL 3 +#define PSURGE_QUAD_PRIMARY_ARB 4 +#define PSURGE_QUAD_BOARD_ID 6 +#define PSURGE_QUAD_WHICH_CPU 7 +#define PSURGE_QUAD_CKSTOP_RDBK 8 +#define PSURGE_QUAD_RESET_CTL 11 + +#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) +#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) +#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) +#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) + +/* virtual addresses for the above */ +static volatile u8 *hhead_base; +static volatile u8 *quad_base; +static volatile u32 *psurge_pri_intr; +static volatile u8 *psurge_sec_intr; +static volatile u32 *psurge_start; + +/* what sort of powersurge board we have */ +static int psurge_type; + +/* values for psurge_type */ +#define PSURGE_DUAL 0 +#define PSURGE_QUAD_OKEE 1 +#define PSURGE_QUAD_COTTON 2 +#define PSURGE_QUAD_ICEGRASS 3 + +/* l2 cache stuff for dual G4 macs */ +extern void core99_init_l2(void); + +/* + * Set and clear IPIs for powersurge. + */ +static inline void psurge_set_ipi(int cpu) +{ + if (cpu == 0) + in_be32(psurge_pri_intr); + else if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, 0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); +} + +static inline void psurge_clr_ipi(int cpu) +{ + if (cpu > 0) { + if (psurge_type == PSURGE_DUAL) + out_8(psurge_sec_intr, ~0); + else + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); + } +} + +/* + * On powersurge (old SMP powermac architecture) we don't have + * separate IPIs for separate messages like openpic does. Instead + * we have a bitmap for each processor, where a 1 bit means that + * the corresponding message is pending for that processor. + * Ideally each cpu's entry would be in a different cache line. + * -- paulus. + */ +static unsigned long psurge_smp_message[NR_CPUS]; + +void psurge_smp_message_recv(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int msg; + + /* clear interrupt */ + psurge_clr_ipi(cpu); + + if (smp_num_cpus < 2) + return; + + /* make sure there is a message there */ + for (msg = 0; msg < 4; msg++) + if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) + smp_message_recv(msg, regs); +} + +void +psurge_primary_intr(int irq, void *d, struct pt_regs *regs) +{ + psurge_smp_message_recv(regs); +} + +static void +smp_psurge_message_pass(int target, int msg, unsigned long data, int wait) +{ + int i; + + if (smp_num_cpus < 2) + return; + + for (i = 0; i < smp_num_cpus; i++) { + if (target == MSG_ALL + || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) + || target == i) { + set_bit(msg, &psurge_smp_message[i]); + psurge_set_ipi(i); + } + } +} + +/* + * Determine a quad card presence. We read the board ID register, we + * force the data bus to change to something else, and we read it again. + * It it's stable, then the register probably exist (ugh !) + */ +static int __init psurge_quad_probe(void) +{ + int type; + unsigned int i; + + type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); + if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS + || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + + /* looks OK, try a slightly more rigorous test */ + /* bogus is not necessarily cacheline-aligned, + though I don't suppose that really matters. -- paulus */ + for (i = 0; i < 100; i++) { + volatile u32 bogus[8]; + bogus[(0+i)%8] = 0x00000000; + bogus[(1+i)%8] = 0x55555555; + bogus[(2+i)%8] = 0xFFFFFFFF; + bogus[(3+i)%8] = 0xAAAAAAAA; + bogus[(4+i)%8] = 0x33333333; + bogus[(5+i)%8] = 0xCCCCCCCC; + bogus[(6+i)%8] = 0xCCCCCCCC; + bogus[(7+i)%8] = 0x33333333; + wmb(); + asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); + mb(); + if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) + return PSURGE_DUAL; + } + return type; +} + +static void __init psurge_quad_init(void) +{ + int procbits; + + if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); + procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); + if (psurge_type == PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + else + PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); + mdelay(33); + out_8(psurge_sec_intr, ~0); + PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); + PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); + if (psurge_type != PSURGE_QUAD_ICEGRASS) + PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); + PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); + PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); + mdelay(33); + PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); + mdelay(33); +} + +static int __init smp_psurge_probe(void) +{ + int i, ncpus; + + /* We don't do SMP on the PPC601 -- paulus */ + if (PVR_VER(mfspr(PVR)) == 1) + return 1; + + /* + * The powersurge cpu board can be used in the generation + * of powermacs that have a socket for an upgradeable cpu card, + * including the 7500, 8500, 9500, 9600. + * The device tree doesn't tell you if you have 2 cpus because + * OF doesn't know anything about the 2nd processor. + * Instead we look for magic bits in magic registers, + * in the hammerhead memory controller in the case of the + * dual-cpu powersurge board. -- paulus. + */ + if (find_devices("hammerhead") == NULL) + return 1; + + hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); + quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); + psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; + + psurge_type = psurge_quad_probe(); + if (psurge_type != PSURGE_DUAL) { + psurge_quad_init(); + /* All released cards using this HW design have 4 CPUs */ + ncpus = 4; + } else { + iounmap((void *) quad_base); + if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { + /* not a dual-cpu card */ + iounmap((void *) hhead_base); + return 1; + } + ncpus = 2; + } + + psurge_start = ioremap(PSURGE_START, 4); + psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); + + /* this is not actually strictly necessary -- paulus. */ + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + + if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); + + return ncpus; +} + +static void __init smp_psurge_kick_cpu(int nr) +{ + void (*start)(void) = __secondary_start_psurge; + unsigned long a; + + /* may need to flush here if secondary bats aren't setup */ + for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) + asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); + asm volatile("sync"); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); + + /* setup entry point of secondary processor */ + switch (nr) { + case 2: + start = __secondary_start_psurge2; + break; + case 3: + start = __secondary_start_psurge3; + break; + } + + out_be32(psurge_start, __pa(start)); + mb(); + + psurge_set_ipi(nr); + udelay(10); + psurge_clr_ipi(nr); + + if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); +} + +/* + * With the dual-cpu powersurge board, the decrementers and timebases + * of both cpus are frozen after the secondary cpu is started up, + * until we give the secondary cpu another interrupt. This routine + * uses this to get the timebases synchronized. + * -- paulus. + */ +static void __init psurge_dual_sync_tb(int cpu_nr) +{ + static volatile int sec_tb_reset = 0; + int t; + + set_dec(tb_ticks_per_jiffy); + set_tb(0, 0); + last_jiffy_stamp(cpu_nr) = 0; + + if (cpu_nr > 0) { + mb(); + sec_tb_reset = 1; + return; + } + + /* wait for the secondary to have reset its TB before proceeding */ + for (t = 10000000; t > 0 && !sec_tb_reset; --t) + ; + + /* now interrupt the secondary, starting both TBs */ + psurge_set_ipi(1); + + smp_tb_synchronized = 1; +} + +static void __init +smp_psurge_setup_cpu(int cpu_nr) +{ + + if (cpu_nr == 0) { + if (smp_num_cpus < 2) + return; + /* reset the entry point so if we get another intr we won't + * try to startup again */ + out_be32(psurge_start, 0x100); + if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0)) + printk(KERN_ERR "Couldn't get primary IPI interrupt"); + } + + if (psurge_type == PSURGE_DUAL) + psurge_dual_sync_tb(cpu_nr); +} + +static int +smp_core99_probe(void) +{ + struct device_node *cpus; + int i, ncpus = 1; + + if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); + cpus = find_type_devices("cpu"); + if (cpus) + while ((cpus = cpus->next) != NULL) + ++ncpus; + printk("smp_core99_probe: found %d cpus\n", ncpus); + if (ncpus > 1) { + openpic_request_IPIs(); + for (i = 1; i < ncpus; ++i) + smp_hw_index[i] = i; + } + + return ncpus; +} + +static void +smp_core99_kick_cpu(int nr) +{ + unsigned long save_vector, new_vector; + unsigned long flags; +#if 1 /* New way... */ + volatile unsigned long *vector + = ((volatile unsigned long *)(KERNELBASE+0x100)); + if (nr < 1 || nr > 3) + return; +#else + volatile unsigned long *vector + = ((volatile unsigned long *)(KERNELBASE+0x500)); + if (nr != 1) + return; +#endif + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector that does + * b __secondary_start_psurge - KERNELBASE + */ + switch(nr) { + case 1: + new_vector = (unsigned long)__secondary_start_psurge; + break; + case 2: + new_vector = (unsigned long)__secondary_start_psurge2; + break; + case 3: + new_vector = (unsigned long)__secondary_start_psurge3; + break; + } + *vector = 0x48000002 + new_vector - KERNELBASE; + + /* flush data cache and inval instruction cache */ + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + /* Put some life in our friend */ + feature_core99_kick_cpu(nr); + + /* FIXME: We wait a bit for the CPU to take the exception, I should + * instead wait for the entry code to set something for me. Well, + * ideally, all that crap will be done in prom.c and the CPU left + * in a RAM-based wait loop like CHRP. + */ + mdelay(1); + + /* Restore our exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); +} + +static void __init +smp_core99_setup_cpu(int cpu_nr) +{ + /* Setup openpic */ + do_openpic_setup_cpu(); + + /* Setup L2 */ + if (cpu_nr != 0) + core99_init_l2(); + else + if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); +} + +/* PowerSurge-style Macs */ +struct smp_ops_t psurge_smp_ops = { + smp_psurge_message_pass, + smp_psurge_probe, + smp_psurge_kick_cpu, + smp_psurge_setup_cpu, +}; + +/* Core99 Macs (dual G4s) */ +struct smp_ops_t core99_smp_ops = { + smp_openpic_message_pass, + smp_core99_probe, + smp_core99_kick_cpu, + smp_core99_setup_cpu, +}; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c --- v2.4.9/linux/arch/ppc/kernel/pmac_time.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/pmac_time.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.pmac_time.c 1.11 07/06/01 15:46:39 trini + * BK Id: SCCS/s.pmac_time.c 1.14 08/19/01 22:23:04 paulus */ /* * Support for periodic interrupts (100 per second) and for getting @@ -260,8 +260,13 @@ pmu_register_sleep_notifier(&time_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ - if (via_calibrate_decr()) - return; + /* We assume MacRISC2 machines have correct device-tree + * calibration. That's better since the VIA itself seems + * to be slightly off. --BenH + */ + if (!machine_is_compatible("MacRISC2")) + if (via_calibrate_decr()) + return; /* * The cpu node should have a timebase-frequency property diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h --- v2.4.9/linux/arch/ppc/kernel/ppc_asm.h Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/ppc_asm.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_asm.h 1.14 07/02/01 22:08:05 paulus + * BK Id: SCCS/s.ppc_asm.h 1.16 08/15/01 22:43:06 paulus */ /* * arch/ppc/kernel/ppc_asm.h @@ -70,20 +70,35 @@ #define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base) #ifdef CONFIG_PPC601_SYNC_FIX -#define SYNC \ - sync; \ - isync +#define SYNC \ +BEGIN_FTR_SECTION \ + sync; \ + isync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#define SYNC_601 \ +BEGIN_FTR_SECTION \ + sync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) +#define ISYNC_601 \ +BEGIN_FTR_SECTION \ + isync; \ +END_FTR_SECTION_IFSET(CPU_FTR_601) #else #define SYNC +#define SYNC_601 +#define ISYNC_601 #endif #ifndef CONFIG_SMP #define TLBSYNC #else /* CONFIG_SMP */ +/* tlbsync is not implemented on 601 */ #define TLBSYNC \ +BEGIN_FTR_SECTION \ tlbsync; \ - sync -#endif /* CONFIG_SMP */ + sync; \ +END_FTR_SECTION_IFCLR(CPU_FTR_601) +#endif /* * This instruction is not implemented on the PPC 603 or 601; however, on diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c --- v2.4.9/linux/arch/ppc/kernel/ppc_htab.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/ppc_htab.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_htab.c 1.11 06/28/01 15:50:16 paulus + * BK Id: SCCS/s.ppc_htab.c 1.17 08/20/01 22:59:41 paulus */ /* * PowerPC hash table management proc entry. Will show information @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,8 @@ #include #include #include +#include +#include static ssize_t ppc_htab_read(struct file * file, char * buf, size_t count, loff_t *ppos); @@ -67,7 +70,7 @@ write: ppc_htab_write, }; -char *pmc1_lookup(unsigned long mmcr0) +static char *pmc1_lookup(unsigned long mmcr0) { switch ( mmcr0 & (0x7f<<7) ) { @@ -84,7 +87,7 @@ } } -char *pmc2_lookup(unsigned long mmcr0) +static char *pmc2_lookup(unsigned long mmcr0) { switch ( mmcr0 & 0x3f ) { @@ -121,11 +124,7 @@ if (count < 0) return -EINVAL; - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { asm volatile ("mfspr %0,952 \n\t" "mfspr %1,953 \n\t" "mfspr %2,954 \n\t" @@ -141,12 +140,9 @@ "PMC2\t\t: %08lx (%s)\n", pmc1, pmc1_lookup(mmcr0), pmc2, pmc2_lookup(mmcr0)); - break; - default: - break; } - +#ifdef CONFIG_PPC_STD_MMU /* if we don't have a htab */ if ( Hash_size == 0 ) { @@ -154,7 +150,6 @@ goto return_string; } -#if !defined(CONFIG_8xx) && !defined(CONFIG_4xx) for ( ptr = Hash ; ptr < Hash_end ; ptr++) { unsigned int ctx, mctx, vsid; @@ -211,7 +206,7 @@ "Evicts\t\t: %lu\n", htab_reloads, htab_preloads, htab_hash_searches, primary_pteg_full, htab_evicts); -#endif /* !8xx && !4xx */ +#endif /* CONFIG_PPC_STD_MMU */ return_string: n += sprintf( buffer + n, @@ -235,7 +230,7 @@ static ssize_t ppc_htab_write(struct file * file, const char * buffer, size_t count, loff_t *ppos) { -#ifndef CONFIG_8xx +#ifdef CONFIG_PPC_STD_MMU unsigned long tmp; if ( current->uid != 0 ) return -EACCES; @@ -246,37 +241,22 @@ /* turn off performance monitoring */ if ( !strncmp( buffer, "off", 3) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { asm volatile ("mtspr %0, %3 \n\t" "mtspr %1, %3 \n\t" "mtspr %2, %3 \n\t" :: "i" (MMCR0), "i" (PMC1), "i" (PMC2), "r" (0)); - break; - default: - break; } - } if ( !strncmp( buffer, "reset", 5) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* reset PMC1 and PMC2 */ asm volatile ( "mtspr 953, %0 \n\t" "mtspr 954, %0 \n\t" :: "r" (0)); - break; - default: - break; } htab_reloads = 0; htab_evicts = 0; @@ -286,11 +266,7 @@ if ( !strncmp( buffer, "user", 4) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x60000000); @@ -301,19 +277,12 @@ "mtspr %5,%4 \n\t" /* reset the pmc2 */ :: "r" (tmp), "i" (MMCR0), "i" (0), "i" (PMC1), "r" (0), "i"(PMC2) ); - break; - default: - break; } } if ( !strncmp( buffer, "kernel", 6) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x60000000); @@ -324,20 +293,13 @@ "mtspr %5,%4 \n\t" /* reset the pmc2 */ :: "r" (tmp), "i" (MMCR0), "i" (0), "i" (PMC1), "r" (0), "i"(PMC2) ); - break; - default: - break; } } /* PMC1 values */ if ( !strncmp( buffer, "dtlb", 4) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x7f<<7); @@ -352,11 +314,7 @@ if ( !strncmp( buffer, "ic miss", 7) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm("mfspr %0,%1\n\t" : "=r" (tmp) : "i" (MMCR0)); tmp &= ~(0x7f<<7); @@ -372,11 +330,7 @@ /* PMC2 values */ if ( !strncmp( buffer, "load miss time", 14) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm volatile( "mfspr %0,%1\n\t" /* get current mccr0 */ @@ -392,11 +346,7 @@ if ( !strncmp( buffer, "itlb", 4) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm volatile( "mfspr %0,%1\n\t" /* get current mccr0 */ @@ -412,11 +362,7 @@ if ( !strncmp( buffer, "dc miss", 7) ) { - switch ( _get_PVR()>>16 ) - { - case 4: /* 604 */ - case 9: /* 604e */ - case 10: /* 604ev5 */ + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) { /* setup mmcr0 and clear the correct pmc */ asm volatile( "mfspr %0,%1\n\t" /* get current mccr0 */ @@ -472,9 +418,9 @@ reset_SDR1(); #endif return count; -#else /* CONFIG_8xx */ +#else /* CONFIG_PPC_STD_MMU */ return 0; -#endif /* CONFIG_8xx */ +#endif /* CONFIG_PPC_STD_MMU */ } @@ -516,7 +462,7 @@ "0.5", "1.0", "(reserved2)", "(reserved3)" }; - if ( ((_get_PVR() >> 16) != 8) && ((_get_PVR() >> 16) != 12)) + if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)) return -EFAULT; if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) { @@ -526,7 +472,7 @@ vleft = table->maxlen / sizeof(int); left = *lenp; - + for (; left /*&& vleft--*/; first=0) { if (write) { while (left) { @@ -556,7 +502,6 @@ buffer += len; left -= len; _set_L2CR(val); - } else { p = buf; if (!first) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.4.9/linux/arch/ppc/kernel/ppc_ksyms.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/ppc_ksyms.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ppc_ksyms.c 1.38 07/23/01 15:35:53 trini + * BK Id: SCCS/s.ppc_ksyms.c 1.51 08/24/01 17:05:47 paulus */ #include #include @@ -48,6 +48,8 @@ #include #endif /* CONFIG_SMP */ #include +#include +#include #ifdef CONFIG_8xx #include "../8xx_io/commproc.h" @@ -73,6 +75,8 @@ int abs(int); extern unsigned long ret_to_user_hook; +extern unsigned long mm_ptov (unsigned long paddr); + EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(syscall_trace); @@ -157,16 +161,10 @@ EXPORT_SYMBOL(ioremap); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); +EXPORT_SYMBOL(iopa); +EXPORT_SYMBOL(mm_ptov); -EXPORT_SYMBOL(ide_insw); -EXPORT_SYMBOL(ide_outsw); EXPORT_SYMBOL(ppc_ide_md); -#ifdef CONFIG_BLK_DEV_IDE_MODULE -EXPORT_SYMBOL(chrp_ide_irq); -EXPORT_SYMBOL(chrp_ide_ports_known); -EXPORT_SYMBOL(chrp_ide_regbase); -EXPORT_SYMBOL(chrp_ide_probe); -#endif #ifdef CONFIG_PCI EXPORT_SYMBOL_NOVERS(isa_io_base); @@ -183,10 +181,10 @@ /*EXPORT_SYMBOL(_disable_interrupts); EXPORT_SYMBOL(_enable_interrupts);*/ EXPORT_SYMBOL(flush_instruction_cache); -EXPORT_SYMBOL(_get_PVR); EXPORT_SYMBOL(giveup_fpu); EXPORT_SYMBOL(enable_kernel_fp); EXPORT_SYMBOL(flush_icache_range); +EXPORT_SYMBOL(flush_dcache_range); EXPORT_SYMBOL(xchg_u32); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(last_task_used_altivec); @@ -200,6 +198,7 @@ EXPORT_SYMBOL(__global_sti); EXPORT_SYMBOL(__global_save_flags); EXPORT_SYMBOL(__global_restore_flags); +#ifdef SPINLOCK_DEBUG EXPORT_SYMBOL(_spin_lock); EXPORT_SYMBOL(_spin_unlock); EXPORT_SYMBOL(spin_trylock); @@ -207,6 +206,7 @@ EXPORT_SYMBOL(_read_unlock); EXPORT_SYMBOL(_write_lock); EXPORT_SYMBOL(_write_unlock); +#endif EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(smp_hw_index); EXPORT_SYMBOL(smp_num_cpus); @@ -226,17 +226,6 @@ EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU -EXPORT_SYMBOL(pmu_request); -EXPORT_SYMBOL(pmu_poll); -EXPORT_SYMBOL(pmu_suspend); -EXPORT_SYMBOL(pmu_resume); -#endif /* CONFIG_ADB_PMU */ -#ifdef CONFIG_PMAC_PBOOK -EXPORT_SYMBOL(pmu_register_sleep_notifier); -EXPORT_SYMBOL(pmu_unregister_sleep_notifier); -EXPORT_SYMBOL(pmu_enable_irled); -#endif /* CONFIG_PMAC_PBOOK */ #ifdef CONFIG_PMAC_BACKLIGHT EXPORT_SYMBOL(get_backlight_level); EXPORT_SYMBOL(set_backlight_level); @@ -245,7 +234,6 @@ #endif /* CONFIG_PMAC_BACKLIGHT */ #if defined(CONFIG_ALL_PPC) EXPORT_SYMBOL(_machine); -EXPORT_SYMBOL_NOVERS(have_of); EXPORT_SYMBOL_NOVERS(sys_ctrler); EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); @@ -273,10 +261,11 @@ EXPORT_SYMBOL(feature_set_usb_power); EXPORT_SYMBOL(feature_set_firewire_power); EXPORT_SYMBOL(feature_set_firewire_cable_power); +EXPORT_SYMBOL(feature_set_modem_power); EXPORT_SYMBOL(feature_set_airport_power); #endif /* defined(CONFIG_ALL_PPC) */ #if defined(CONFIG_BOOTX_TEXT) -EXPORT_SYMBOL(bootx_update_display); +EXPORT_SYMBOL(btext_update_display); #endif #if defined(CONFIG_SCSI) && defined(CONFIG_ALL_PPC) EXPORT_SYMBOL(note_scsi_host); @@ -303,7 +292,7 @@ EXPORT_SYMBOL(abs); -#ifdef CONFIG_VT +#ifdef CONFIG_VGA_CONSOLE EXPORT_SYMBOL(screen_info); #endif @@ -367,3 +356,4 @@ #endif extern long *ret_from_intercept; EXPORT_SYMBOL(ret_from_intercept); +EXPORT_SYMBOL(cur_cpu_spec); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c --- v2.4.9/linux/arch/ppc/kernel/prep_pci.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/prep_pci.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prep_pci.c 1.22 08/05/01 16:18:54 trini + * BK Id: SCCS/s.prep_pci.c 1.24 08/20/01 15:06:15 paulus */ /* * PReP pci functions. @@ -172,7 +172,7 @@ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unxued */ + 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 0, /* Slot 12 - unused */ 0, /* Slot 13 - unused */ @@ -200,7 +200,7 @@ 0, /* Slot 7 - unused */ 0, /* Slot 8 - unused */ 0, /* Slot 9 - unused */ - 0, /* Slot 10 - unxued */ + 0, /* Slot 10 - unused */ 0, /* Slot 11 - unused */ 0, /* Slot 12 - unused */ 0, /* Slot 13 - unused */ @@ -322,8 +322,8 @@ 3, /* Slot 12 - unused */ 0, /* Slot 13 - unused */ 2, /* Slot 14 - SCSI */ - 0, /* Slot 15 - graphics on 3600 */ - 9, /* Slot 16 - PMC */ + 0, /* Slot 15 - unused */ + 9, /* Slot 16 - PMC 1 */ 12, /* Slot 17 - pci */ 11, /* Slot 18 - pci */ 10, /* Slot 19 - pci */ @@ -511,6 +511,44 @@ 13 /* Line 4 */ }; +/* + * IBM RS/6000 43p/140 -- paulus + * XXX we should get all this from the residual data + */ +static char ibm43p_pci_IRQ_map[23] __prepdata = { + 0, /* Slot 0 - unused */ + 0, /* Slot 1 - unused */ + 0, /* Slot 2 - unused */ + 0, /* Slot 3 - unused */ + 0, /* Slot 4 - unused */ + 0, /* Slot 5 - unused */ + 0, /* Slot 6 - unused */ + 0, /* Slot 7 - unused */ + 0, /* Slot 8 - unused */ + 0, /* Slot 9 - unused */ + 0, /* Slot 10 - unused */ + 0, /* Slot 11 - FireCoral ISA bridge */ + 6, /* Slot 12 - Ethernet */ + 0, /* Slot 13 - openpic */ + 0, /* Slot 14 - unused */ + 0, /* Slot 15 - unused */ + 7, /* Slot 16 - NCR58C825a onboard scsi */ + 0, /* Slot 17 - unused */ + 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */ + 0, /* Slot 19 - unused */ + 0, /* Slot 20 - unused */ + 0, /* Slot 21 - unused */ + 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ +}; + +static char ibm43p_pci_IRQ_routes[] __prepdata = { + 0, /* Line 0 - unused */ + 15, /* Line 1 */ + 15, /* Line 2 */ + 15, /* Line 3 */ + 15, /* Line 4 */ +}; + /* Motorola PowerPlus architecture PCI IRQ tables */ /* Interrupt line values for INTA-D on primary/secondary MPIC inputs */ @@ -767,7 +805,52 @@ {0x000, 0x00, 0x00, "", NULL, NULL, NULL, NULL, 0x00} }; -unsigned long __init prep_route_pci_interrupts(void) +void ibm_prep_init(void) +{ + u32 addr; +#ifdef CONFIG_PREP_RESIDUAL + PPC_DEVICE *mpic; +#endif + + if (inb(0x0852) == 0xd5) { + /* This is for the 43p-140 */ + early_read_config_dword(0, 0, PCI_DEVFN(13, 0), + PCI_BASE_ADDRESS_0, &addr); + if (addr != 0xffffffff + && !(addr & PCI_BASE_ADDRESS_SPACE_IO) + && (addr &= PCI_BASE_ADDRESS_MEM_MASK) != 0) { + addr += PREP_ISA_MEM_BASE; + OpenPIC_Addr = ioremap(addr, 0x40000); + ppc_md.get_irq = openpic_get_irq; + } + } + +#ifdef CONFIG_PREP_RESIDUAL + mpic = residual_find_device(-1, NULL, SystemPeripheral, + ProgrammableInterruptController, MPIC, 0); + if (mpic != NULL) { + printk("mpic = %p\n", mpic); + } +#endif +} + +void +ibm43p_pci_map_non0(struct pci_dev *dev) +{ + unsigned char intpin; + static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 }; + + if (dev == NULL) + return; + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin); + if (intpin < 1 || intpin > 4) + return; + intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3; + dev->irq = openpic_to_irq(bridge_intrs[intpin]); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); +} + +void __init prep_route_pci_interrupts(void) { unsigned char *ibc_pirq = (unsigned char *)0x80800860; unsigned char *ibc_pcicon = (unsigned char *)0x80800840; @@ -856,7 +939,13 @@ Motherboard_map_name = "IBM 6015"; Motherboard_map = ibm6015_pci_IRQ_map; Motherboard_routes = ibm6015_pci_IRQ_routes; - break; + break; + case 0xd5: + Motherboard_map_name = "IBM 43p/140"; + Motherboard_map = ibm43p_pci_IRQ_map; + Motherboard_routes = ibm43p_pci_IRQ_routes; + Motherboard_non0 = ibm43p_pci_map_non0; + break; default: Motherboard_map_name = "IBM 8xx (Carolina)"; Motherboard_map = ibm8xx_pci_IRQ_map; @@ -878,7 +967,7 @@ else { printk("No known machine pci routing!\n"); - return -1; + return; } /* Set up mapping from slots */ @@ -888,16 +977,15 @@ } /* Enable PCI interrupts */ *ibc_pcicon |= 0x20; - return 0; } void __init prep_pib_init(void) { -unsigned char reg; -unsigned short short_reg; + unsigned char reg; + unsigned short short_reg; -struct pci_dev *dev = NULL; + struct pci_dev *dev = NULL; if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) { /* @@ -910,43 +998,47 @@ * PPCBUG does not set the enable bits * for the IDE device. Force them on here. */ - pcibios_read_config_byte(dev->bus->number, - dev->devfn, 0x40, ®); + pci_read_config_byte(dev, 0x40, ®); reg |= 0x03; /* IDE: Chip Enable Bits */ - pcibios_write_config_byte(dev->bus->number, - dev->devfn, 0x40, reg); - - /* Force correct IDE function interrupt */ - dev->irq = 14; - pcibios_write_config_byte(dev->bus->number, - dev->devfn, + pci_write_config_byte(dev, 0x40, reg); + } + if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, + dev)) && (dev->devfn = 0x5a)) { + /* Force correct USB interrupt */ + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - - } else if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + } + if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, dev))) { - /* - * Clear the PCI Interrupt Routing Control Register. - */ + /* Clear PCI Interrupt Routing Control Register. */ short_reg = 0x0000; pci_write_config_word(dev, 0x44, short_reg); if (OpenPIC_Addr){ - /* - * Route both IDE interrupts to IRQ 14 - */ + /* Route IDE interrupts to IRQ 14 */ reg = 0xEE; - pci_write_config_byte(dev, 0x44, reg); + pci_write_config_byte(dev, 0x43, reg); } } } + if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev))){ if (OpenPIC_Addr){ - /* Disable LEGIRQ mode so PCI INTs are routed to - the 8259 */ - printk("Set winbond IDE to native mode\n"); - pci_write_config_dword(dev, 0x40, 0x10ff00a1); + /* + * Disable LEGIRQ mode so PCI INTS are routed + * directly to the 8259 and enable both channels + */ + pci_write_config_dword(dev, 0x40, 0x10ff0033); + + /* Force correct IDE interrupt */ + dev->irq = 14; + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + dev->irq); }else{ /* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */ pci_write_config_dword(dev, 0x40, 0x10ff08a1); @@ -1106,6 +1198,19 @@ } } +static void __init +prep_init_resource(struct resource *res, unsigned long start, + unsigned long end, int flags) +{ + res->flags = flags; + res->start = start; + res->end = end; + res->name = "PCI host bridge"; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; +} + void __init prep_find_bridges(void) { @@ -1119,6 +1224,9 @@ hose->last_busno = 0xff; hose->pci_mem_offset = PREP_ISA_MEM_BASE; hose->io_base_virt = (void *)PREP_ISA_IO_BASE; + prep_init_resource(&hose->io_resource, 0, 0x0fffffff, IORESOURCE_IO); + prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff, + IORESOURCE_MEM); printk("PReP architecture\n"); { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.4.9/linux/arch/ppc/kernel/prep_setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/prep_setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prep_setup.c 1.26 08/05/01 16:18:54 trini + * BK Id: SCCS/s.prep_setup.c 1.32 08/20/01 15:06:15 paulus */ /* * linux/arch/ppc/kernel/setup.c @@ -7,6 +7,9 @@ * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas * Modified by Cort Dougan (cort@cs.nmt.edu) + * + * Support for PReP (Motorola MTX/MVME) + * by Troy Benjegerdes (hozer@drgw.net) */ /* @@ -78,6 +81,7 @@ extern unsigned char rs_nvram_read_val(int addr); extern void rs_nvram_write_val(int addr, unsigned char val); +extern void ibm_prep_init(void); extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); @@ -85,6 +89,7 @@ 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]; @@ -329,13 +334,20 @@ /*print_residual_device_info();*/ - raven_init(); + switch (_prep_type) { + case _PREP_Motorola: + raven_init(); + break; + case _PREP_IBM: + ibm_prep_init(); + break; + } #ifdef CONFIG_VGA_CONSOLE /* remap the VGA memory */ vgacon_remap_base = 0xf0000000; /*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/ - conswitchp = &vga_con; + conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif @@ -662,23 +674,6 @@ } } -#if 0 -void __prep -prep_do_IRQ(struct pt_regs *regs, int cpu) -{ - int irq; - - if ( (irq = i8259_irq(0)) < 0 ) - { - printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n", - regs->nip); - ppc_spurious_interrupts++; - return; - } - ppc_irq_dispatch_handler( regs, irq ); -} -#endif - int __prep prep_get_irq(struct pt_regs *regs) { @@ -701,18 +696,6 @@ /* * IDE stuff. */ -void __prep -prep_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - _insw((unsigned short *)((port)+_IO_BASE), buf, ns); -} - -void __prep -prep_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - _outsw((unsigned short *)((port)+_IO_BASE), buf, ns); -} - int __prep prep_ide_default_irq(ide_ioreg_t base) { @@ -721,8 +704,9 @@ case 0x170: return 13; case 0x1e8: return 11; case 0x168: return 10; - default: - return 0; + case 0xfff0: return 14; /* MCP(N)750 ide0 */ + case 0xffe0: return 15; /* MCP(N)750 ide1 */ + default: return 0; } } @@ -780,6 +764,45 @@ } #endif +#ifdef CONFIG_SMP +/* PReP (MTX) support */ +static int +smp_prep_probe(void) +{ + extern int mot_multi; + + if (mot_multi) { + openpic_request_IPIs(); + smp_hw_index[1] = 1; + return 2; + } + + return 1; +} + +static void +smp_prep_kick_cpu(int nr) +{ + *(unsigned long *)KERNELBASE = nr; + asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); + printk("CPU1 reset, waiting\n"); +} + +static void +smp_prep_setup_cpu(int cpu_nr) +{ + if (OpenPIC_Addr) + do_openpic_setup_cpu(); +} + +static struct smp_ops_t prep_smp_ops = { + smp_openpic_message_pass, + smp_prep_probe, + smp_prep_kick_cpu, + smp_prep_setup_cpu, +}; +#endif /* CONFIG_SMP */ + /* * This finds the amount of physical ram and does necessary * setup for prep. This is pretty architecture specific so @@ -788,29 +811,39 @@ */ unsigned long __init prep_find_end_of_memory(void) { - unsigned long total; + unsigned long total = 0; + extern unsigned int boot_mem_size; + #ifdef CONFIG_PREP_RESIDUAL total = res->TotalMemory; -#else - total = 0; #endif - if (total == 0 ) - { + if (total == 0 && boot_mem_size != 0) + total = boot_mem_size; + + if (total == 0) { /* * I need a way to probe the amount of memory if the residual * data doesn't contain it. -- Cort */ - printk("Ramsize from residual data was 0 -- Probing for value\n"); total = 0x02000000; - printk("Ramsize default to be %ldM\n", total>>20); + printk(KERN_INFO "Ramsize from residual data was 0" + " -- defaulting to %ldM\n", total>>20); } return (total); } -unsigned long *MotSave_SmpIar; -unsigned char *MotSave_CpusState[2]; +/* + * Setup the bat mappings we're going to load that cover + * the io areas. RAM was mapped by mapin_ram(). + * -- Cort + */ +void __init prep_map_io(void) +{ + io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); + io_block_mapping(0xf0000000, 0xc0000000, 0x08000000, _PAGE_IO); +} void __init prep_init2(void) @@ -838,13 +871,6 @@ { memcpy((void *)res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL)); - - /* These need to be saved for the Motorola Prep - * MVME4600 and Dual MTX boards. - */ - MotSave_SmpIar = &old_res->VitalProductData.SmpIar; - MotSave_CpusState[0] = &old_res->Cpus[0].CpuState; - MotSave_CpusState[1] = &old_res->Cpus[1].CpuState; } #endif @@ -912,19 +938,16 @@ } ppc_md.find_end_of_memory = prep_find_end_of_memory; + ppc_md.setup_io_mappings = prep_map_io; #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = prep_ide_insw; - ppc_ide_md.outsw = prep_ide_outsw; ppc_ide_md.default_irq = prep_ide_default_irq; ppc_ide_md.default_io_base = prep_ide_default_io_base; ppc_ide_md.ide_check_region = prep_ide_check_region; ppc_ide_md.ide_request_region = prep_ide_request_region; ppc_ide_md.ide_release_region = prep_ide_release_region; - ppc_ide_md.fix_driveid = NULL; ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports; -#endif - ppc_ide_md.io_base = _IO_BASE; +#endif #ifdef CONFIG_VT ppc_md.kbd_setkeycode = pckbd_setkeycode; @@ -932,10 +955,15 @@ ppc_md.kbd_translate = pckbd_translate; ppc_md.kbd_unexpected_up = pckbd_unexpected_up; ppc_md.kbd_leds = pckbd_leds; + ppc_md.kbd_rate_fn = pckbd_rate; ppc_md.kbd_init_hw = pckbd_init_hw; #ifdef CONFIG_MAGIC_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; SYSRQ_KEY = 0x54; #endif #endif + +#ifdef CONFIG_SMP + ppc_md.smp_ops = &prep_smp_ops; +#endif /* CONFIG_SMP */ } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.4.9/linux/arch/ppc/kernel/process.c Wed Jul 25 17:10:18 2001 +++ linux/arch/ppc/kernel/process.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.process.c 1.23 07/19/01 23:02:48 paulus + * BK Id: SCCS/s.process.c 1.27 08/28/01 22:01:21 paulus */ /* * linux/arch/ppc/kernel/process.c @@ -59,8 +59,6 @@ }; /* only used to get secondary processor up */ struct task_struct *current_set[NR_CPUS] = {&init_task, }; -char *sysmap = NULL; -unsigned long sysmap_size = 0; #undef SHOW_TASK_SWITCHES #undef CHECK_STACK @@ -324,7 +322,6 @@ unsigned long unused, struct task_struct *p, struct pt_regs *regs) { - unsigned long msr; struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); unsigned long sp = (unsigned long)p + sizeof(union task_union); @@ -362,11 +359,12 @@ * copy fpu info - assume lazy fpu switch now always * -- Cort */ - if (regs->msr & MSR_FP) + if (regs->msr & MSR_FP) { giveup_fpu(current); + childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + } memcpy(&p->thread.fpr, ¤t->thread.fpr, sizeof(p->thread.fpr)); p->thread.fpscr = current->thread.fpscr; - childregs->msr &= ~MSR_FP; #ifdef CONFIG_ALTIVEC /* diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c --- v2.4.9/linux/arch/ppc/kernel/prom.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/prom.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prom.c 1.35 07/25/01 14:11:37 trini + * BK Id: SCCS/s.prom.c 1.40 08/24/01 20:13:31 paulus */ /* * Procedures for interfacing to the Open Firmware PROM on @@ -33,6 +33,7 @@ #include #include #include +#include #include "open_pic.h" #ifdef CONFIG_FB @@ -99,6 +100,7 @@ #define FB_MAX 8 #endif char *prom_display_paths[FB_MAX] __initdata = { 0, }; +phandle prom_display_nodes[FB_MAX] __initdata; unsigned int prom_num_displays __initdata = 0; char *of_stdout_device __initdata = 0; ihandle prom_disp_node __initdata = 0; @@ -125,40 +127,6 @@ static struct device_node *allnodes; -#ifdef CONFIG_BOOTX_TEXT - -#define NO_SCROLL - -static void clearscreen(void); -static void flushscreen(void); - -#ifndef NO_SCROLL -static void scrollscreen(void); -#endif - -static void prepare_disp_BAT(void); - -static void draw_byte(unsigned char c, long locX, long locY); -static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb); -static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb); -static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb); - -static int g_loc_X; -static int g_loc_Y; -static int g_max_loc_X; -static int g_max_loc_Y; - -unsigned long disp_BAT[2] __initdata = {0, 0}; - -#define cmapsz (16*256) - -static unsigned char vga_font[cmapsz]; - -int bootx_text_mapped = 1; - -#endif /* CONFIG_BOOTX_TEXT */ - - static void *call_prom(const char *service, int nargs, int nret, ...); static void prom_exit(void); static unsigned long copy_device_tree(unsigned long, unsigned long); @@ -174,7 +142,6 @@ #ifdef CONFIG_BOOTX_TEXT static void setup_disp_fake_bi(ihandle dp); -static void prom_welcome(boot_infos_t* bi, unsigned long phys); #endif extern void enter_rtas(void *); @@ -182,10 +149,6 @@ extern char cmd_line[512]; /* XXX */ boot_infos_t *boot_infos; -#ifdef CONFIG_BOOTX_TEXT -boot_infos_t *disp_bi; -boot_infos_t fake_bi; -#endif unsigned long dev_tree_size; #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) @@ -257,13 +220,7 @@ unsigned long offset = reloc_offset(); if (RELOC(prom_stdout) == 0) - { -#ifdef CONFIG_BOOTX_TEXT - if (RELOC(disp_bi) != 0) - prom_drawstring(msg); -#endif return; - } for (p = msg; *p != 0; p = q) { for (q = p; *q != 0 && *q != '\n'; ++q) @@ -399,26 +356,21 @@ bi->logicalDisplayBase = 0; #ifdef CONFIG_BOOTX_TEXT - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; - RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; - RELOC(disp_bi) = PTRUNRELOC(bi); - - clearscreen(); + btext_init(bi); - /* Test if boot-info is compatible. Done only in config CONFIG_BOOTX_TEXT since - there is nothing much we can do with an incompatible version, except display - a message and eventually hang the processor... - - I'll try to keep enough of boot-info compatible in the future to always allow - display of this message; - */ - if (!BOOT_INFO_IS_COMPATIBLE(bi)) - prom_print(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n")); - - prom_welcome(bi, phys); - flushscreen(); + /* + * Test if boot-info is compatible. Done only in config + * CONFIG_BOOTX_TEXT since there is nothing much we can do + * with an incompatible version, except display a message + * and eventually hang the processor... + * + * I'll try to keep enough of boot-info compatible in the + * future to always allow display of this message; + */ + if (!BOOT_INFO_IS_COMPATIBLE(bi)) { + btext_drawstring(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n")); + btext_flushscreen(); + } #endif /* CONFIG_BOOTX_TEXT */ /* New BootX enters kernel with MMU off, i/os are not allowed @@ -461,10 +413,13 @@ } #ifdef CONFIG_BOOTX_TEXT - prepare_disp_BAT(); - prom_drawstring(RELOC("booting...\n")); - flushscreen(); - RELOC(bootx_text_mapped) = 1; + /* + * Note that after we call prepare_disp_BAT, we can't do + * prom_draw*, flushscreen or clearscreen until we turn the MMU + * on, since prepare_disp_BAT sets disp_bi->logicalDisplayBase + * to a virtual address. + */ + btext_prepare_BAT(); #endif } @@ -591,13 +546,11 @@ unsigned long __init prom_init(int r3, int r4, prom_entry pp) { - int chrp = 0; unsigned long mem; - ihandle prom_mmu, prom_op; + ihandle prom_mmu; unsigned long offset = reloc_offset(); int l; char *p, *d; - int prom_version = 0; unsigned long phys; /* Default */ @@ -622,31 +575,6 @@ RELOC(of_stdout_device) = PTRUNRELOC(p); mem += strlen(p) + 1; - /* Find the OF version */ - prom_op = call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom")); - prom_version = 0; - if (prom_op != (void*)-1) { - char model[64]; - int sz; - sz = (int)call_prom(RELOC("getprop"), 4, 1, prom_op, - RELOC("model"), model, 64); - if (sz > 0) { - char *c; - /* hack to skip the ibm chrp firmware # */ - if ( strncmp(model,RELOC("IBM"),3) ) { - for (c = model; *c; c++) - if (*c >= '0' && *c <= '9') { - prom_version = *c - '0'; - break; - } - } - else - chrp = 1; - } - } - if (prom_version >= 3) - prom_print(RELOC("OF Version 3 detected.\n")); - /* Get the boot device and translate it to a full OF pathname. */ p = (char *) mem; l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen), @@ -725,22 +653,14 @@ call_prom(RELOC("quiesce"), 0, 0); #ifdef CONFIG_BOOTX_TEXT - if (!chrp && RELOC(disp_bi)) { - RELOC(prom_stdout) = 0; /* stop OF output */ - clearscreen(); - prepare_disp_BAT(); - prom_welcome(PTRRELOC(RELOC(disp_bi)), phys); - prom_drawstring(RELOC("booting...\n")); - RELOC(bootx_text_mapped) = 1; - } else { - RELOC(bootx_text_mapped) = 0; - } + btext_prepare_BAT(); #endif prom_print(RELOC("returning ")); prom_print_hex(phys); prom_print(RELOC(" from prom_init\n")); RELOC(prom_stdout) = 0; + return phys; } @@ -767,82 +687,6 @@ rtas(&u, RELOC(rtas_data)); } -#ifdef CONFIG_BOOTX_TEXT -static void __init -prom_welcome(boot_infos_t* bi, unsigned long phys) -{ - unsigned long offset = reloc_offset(); - unsigned long flags; - unsigned long pvr; - - prom_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); - prom_drawstring(RELOC("\nstarted at : 0x")); - prom_drawhex(phys); - prom_drawstring(RELOC("\nlinked at : 0x")); - prom_drawhex(KERNELBASE); - prom_drawstring(RELOC("\nframe buffer at : 0x")); - prom_drawhex((unsigned long)bi->dispDeviceBase); - prom_drawstring(RELOC(" (phys), 0x")); - prom_drawhex((unsigned long)bi->logicalDisplayBase); - prom_drawstring(RELOC(" (log)")); - prom_drawstring(RELOC("\nklimit : 0x")); - prom_drawhex((unsigned long)RELOC(klimit)); - prom_drawstring(RELOC("\nMSR : 0x")); - __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); - prom_drawhex(flags); - __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); - pvr >>= 16; - if (pvr > 1) { - prom_drawstring(RELOC("\nHID0 : 0x")); - __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); - prom_drawhex(flags); - } - if (pvr == 8 || pvr == 12 || pvr == 0x800c) { - prom_drawstring(RELOC("\nICTC : 0x")); - __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); - prom_drawhex(flags); - } - prom_drawstring(RELOC("\n\n")); -} - -/* Calc BAT values for mapping the display and store them - * in disp_BAT. Those values are then used from head.S to map - * the display during identify_machine() and MMU_Init() - * - * For now, the display is mapped in place (1:1). This should - * be changed if the display physical address overlaps - * KERNELBASE, which is fortunately not the case on any machine - * I know of. This mapping is temporary and will disappear as - * soon as the setup done by MMU_Init() is applied - * - * For now, we align the BAT and then map 8Mb on 601 and 16Mb - * on other PPCs. This may cause trouble if the framebuffer - * is really badly aligned, but I didn't encounter this case - * yet. - */ -static void __init -prepare_disp_BAT(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long addr = (unsigned long)bi->dispDeviceBase; - - if ((_get_PVR() >> 16) != 1) { - /* 603, 604, G3, G4, ... */ - addr &= 0xFF000000UL; - RELOC(disp_BAT[0]) = addr | (BL_16M<<2) | 2; - RELOC(disp_BAT[1]) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); - } else { - /* 601 */ - addr &= 0xFF800000UL; - RELOC(disp_BAT[0]) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4; - RELOC(disp_BAT[1]) = addr | BL_8M | 0x40; - } - bi->logicalDisplayBase = bi->dispDeviceBase; -} - -#endif - static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) { @@ -920,17 +764,22 @@ i = RELOC(prom_num_displays)++; if (RELOC(of_stdout_device) != 0 && i > 0 && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) { - for (; i > 0; --i) + for (; i > 0; --i) { RELOC(prom_display_paths[i]) = RELOC(prom_display_paths[i-1]); + RELOC(prom_display_nodes[i]) + = RELOC(prom_display_nodes[i-1]); + } } RELOC(prom_display_paths[i]) = PTRUNRELOC(path); + RELOC(prom_display_nodes[i]) = node; if (i == 0) RELOC(prom_disp_node) = node; if (RELOC(prom_num_displays) >= FB_MAX) break; } +try_again: /* * Open the first display and set its colormap. */ @@ -941,6 +790,15 @@ ih = call_prom(RELOC("open"), 1, 1, path); if (ih == 0 || ih == (ihandle) -1) { prom_print(RELOC("... failed\n")); + for (i=1; i 0) + RELOC(prom_disp_node) = RELOC(prom_display_nodes[0]); + else + RELOC(prom_disp_node) = NULL; + goto try_again; } else { prom_print(RELOC("... ok\n")); /* @@ -977,7 +835,6 @@ { int width = 640, height = 480, depth = 8, pitch; unsigned address; - boot_infos_t* bi; unsigned long offset = reloc_offset(); struct pci_reg_property addrs[8]; int i, naddrs; @@ -1025,20 +882,8 @@ /* kludge for valkyrie */ if (strcmp(name, RELOC("valkyrie")) == 0) address += 0x1000; - - RELOC(disp_bi) = &fake_bi; - bi = PTRRELOC((&fake_bi)); - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = width / 8; - RELOC(g_max_loc_Y) = height / 16; - bi->logicalDisplayBase = (unsigned char *)address; - bi->dispDeviceBase = (unsigned char *)address; - bi->dispDeviceRowBytes = pitch; - bi->dispDeviceDepth = depth; - bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; - bi->dispDeviceRect[2] = width; - bi->dispDeviceRect[3] = height; + + btext_setup_display(width, height, depth, pitch, address); } #endif @@ -1147,8 +992,7 @@ prev_propp = &pp->next; namep = (char *) (pp + 1); pp->name = PTRUNRELOC(namep); - /* Work around a GCC3 bug */ - memcpy(namep, RELOC("linux,phandle"), sizeof("linux,phandle")); + strcpy(namep, RELOC("linux,phandle")); mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1); pp->value = (unsigned char *) PTRUNRELOC(&np->node); pp->length = sizeof(np->node); @@ -1213,15 +1057,21 @@ * np->name has not been set yet. -- paulus */ int n = 0; - char *name; + char *name, *ic; + int iclen; for (np = allnodes; np != NULL; np = np->allnext) { - if ((name = get_property(np, "name", NULL)) == NULL - || strcmp(name, "interrupt-controller") != 0) - continue; - if (n == 0) - dflt_interrupt_controller = np; - ++n; + ic = get_property(np, "interrupt-controller", &iclen); + name = get_property(np, "name", NULL); + /* checking iclen makes sure we don't get a false + match on /chosen.interrupt_controller */ + if ((name != NULL + && strcmp(name, "interrupt-controller") == 0) + || (ic != NULL && iclen == 0)) { + if (n == 0) + dflt_interrupt_controller = np; + ++n; + } } num_interrupt_controllers = n; } @@ -1559,7 +1409,7 @@ } } -int __init +int prom_n_addr_cells(struct device_node* np) { int* ip; @@ -1574,7 +1424,7 @@ return 1; } -int __init +int prom_n_size_cells(struct device_node* np) { int* ip; @@ -1890,7 +1740,7 @@ /* * Returns all nodes linked together */ -struct device_node __openfirmware * +struct device_node * __openfirmware find_all_nodes(void) { struct device_node *head, **prevp, *np; @@ -1983,7 +1833,7 @@ /* * Find the device_node with a given phandle. */ -static struct device_node __init * +static struct device_node * __init find_phandle(phandle ph) { struct device_node *np; @@ -2111,6 +1961,12 @@ u.words[i+3] = va_arg(list, unsigned long); va_end(list); + /* Shouldn't we enable kernel FP here ? enter_rtas will play + * with MSR_FE0|MSR_FE1|MSR_FP so I assume rtas might use + * floating points. If that's the case, then we need to make + * sure any lazy FP context is backed up + * --BenH + */ spin_lock_irqsave(&rtas_lock, s); enter_rtas((void *)__pa(&u)); spin_unlock_irqrestore(&rtas_lock, s); @@ -2130,694 +1986,3 @@ for (;;) prom_exit(); } - -#ifdef CONFIG_BOOTX_TEXT - -/* Here's a small text engine to use during early boot or for debugging purposes - * - * todo: - * - * - build some kind of vgacon with it to enable early printk - * - move to a separate file - * - add a few video driver hooks to keep in sync with display - * changes. - */ - -void -map_bootx_text(void) -{ - unsigned long base, offset, size; - if (disp_bi == 0) - return; - base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL; - offset = ((unsigned long) disp_bi->dispDeviceBase) - base; - size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset - + disp_bi->dispDeviceRect[0]; - disp_bi->logicalDisplayBase = ioremap(base, size); - if (disp_bi->logicalDisplayBase == 0) - return; - disp_bi->logicalDisplayBase += offset; - bootx_text_mapped = 1; -} - -/* Calc the base address of a given point (x,y) */ -static unsigned char * __pmac -calc_base(boot_infos_t *bi, int x, int y) -{ - unsigned char *base; - - base = bi->logicalDisplayBase; - if (base == 0) - base = bi->dispDeviceBase; - base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); - base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; - return base; -} - -/* Adjust the display to a new resolution */ -void __openfirmware -bootx_update_display(unsigned long phys, int width, int height, - int depth, int pitch) -{ - if (disp_bi == 0) - return; - /* check it's the same frame buffer (within 64MB) */ - if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) { - return; - } - - disp_bi->dispDeviceBase = (__u8 *) phys; - disp_bi->dispDeviceRect[0] = 0; - disp_bi->dispDeviceRect[1] = 0; - disp_bi->dispDeviceRect[2] = width; - disp_bi->dispDeviceRect[3] = height; - disp_bi->dispDeviceDepth = depth; - disp_bi->dispDeviceRowBytes = pitch; - if (bootx_text_mapped) { - iounmap(disp_bi->logicalDisplayBase); - bootx_text_mapped = 0; - } - map_bootx_text(); - g_loc_X = 0; - g_loc_Y = 0; - g_max_loc_X = width / 8; - g_max_loc_Y = height / 16; -} - -static void __pmac -clearscreen(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - int i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) - { - unsigned long *ptr = base; - for(j=width; j; --j) - *(ptr++) = 0; - base += (bi->dispDeviceRowBytes >> 2); - } -} - -__inline__ void dcbst(const void* addr) -{ - __asm__ __volatile__ ("dcbst 0,%0" :: "r" (addr)); -} - -static void __pmac -flushscreen(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - int i,j; - - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) - { - unsigned long *ptr = base; - for(j=width; j>0; j-=8) { - dcbst(ptr); - ptr += 8; - } - base += (bi->dispDeviceRowBytes >> 2); - } -} - -#ifndef NO_SCROLL -static void __pmac -scrollscreen(void) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned long *src = (unsigned long *)calc_base(bi,0,16); - unsigned long *dst = (unsigned long *)calc_base(bi,0,0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 2; - int i,j; - -#ifdef CONFIG_ADB_PMU - pmu_suspend(); /* PMU will not shut us down ! */ -#endif - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) - { - unsigned long *src_ptr = src; - unsigned long *dst_ptr = dst; - for(j=width; j; --j) - *(dst_ptr++) = *(src_ptr++); - src += (bi->dispDeviceRowBytes >> 2); - dst += (bi->dispDeviceRowBytes >> 2); - } - for (i=0; i<16; i++) - { - unsigned long *dst_ptr = dst; - for(j=width; j; --j) - *(dst_ptr++) = 0; - dst += (bi->dispDeviceRowBytes >> 2); - } -#ifdef CONFIG_ADB_PMU - pmu_resume(); /* PMU will not shut us down ! */ -#endif -} -#endif /* ndef NO_SCROLL */ - -void __pmac -prom_drawchar(char c) -{ - unsigned long offset = reloc_offset(); - int cline = 0, x; - - if (!RELOC(bootx_text_mapped)) - return; - - switch (c) { - case '\b': - if (RELOC(g_loc_X) > 0) - --RELOC(g_loc_X); - break; - case '\t': - RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; - break; - case '\r': - RELOC(g_loc_X) = 0; - break; - case '\n': - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y)++; - cline = 1; - break; - default: - draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); - } - if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y)++; - cline = 1; - } -#ifndef NO_SCROLL - while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { - scrollscreen(); - RELOC(g_loc_Y)--; - } -#else - /* wrap around from bottom to top of screen so we don't - waste time scrolling each line. -- paulus. */ - if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) - RELOC(g_loc_Y) = 0; - if (cline) { - for (x = 0; x < RELOC(g_max_loc_X); ++x) - draw_byte(' ', x, RELOC(g_loc_Y)); - } -#endif -} - -void __pmac -prom_drawstring(const char *c) -{ - unsigned long offset = reloc_offset(); - - if (!RELOC(bootx_text_mapped)) - return; - while (*c) - prom_drawchar(*c++); -} - -void __pmac -prom_drawhex(unsigned long v) -{ - static char hex_table[] = "0123456789abcdef"; - unsigned long offset = reloc_offset(); - - if (!RELOC(bootx_text_mapped)) - return; - prom_drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]); - prom_drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]); -} - -static void __pmac -draw_byte(unsigned char c, long locX, long locY) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); - unsigned char *base = calc_base(bi, locX << 3, locY << 4); - unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16]; - int rb = bi->dispDeviceRowBytes; - - switch(bi->dispDeviceDepth) { - case 32: - draw_byte_32(font, (unsigned long *)base, rb); - break; - case 16: - draw_byte_16(font, (unsigned long *)base, rb); - break; - case 8: - draw_byte_8(font, (unsigned long *)base, rb); - break; - default: - break; - } -} - -static unsigned long expand_bits_8[16] __pmacdata = { - 0x00000000, - 0x000000ff, - 0x0000ff00, - 0x0000ffff, - 0x00ff0000, - 0x00ff00ff, - 0x00ffff00, - 0x00ffffff, - 0xff000000, - 0xff0000ff, - 0xff00ff00, - 0xff00ffff, - 0xffff0000, - 0xffff00ff, - 0xffffff00, - 0xffffffff -}; - -static unsigned long expand_bits_16[4] __pmacdata = { - 0x00000000, - 0x0000ffff, - 0xffff0000, - 0xffffffff -}; - -static void __pmac -draw_byte_32(unsigned char *font, unsigned long *base, int rb) -{ - int l, bits; - int fg = 0xFFFFFFFFUL; - int bg = 0x00000000UL; - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (-(bits >> 7) & fg) ^ bg; - base[1] = (-((bits >> 6) & 1) & fg) ^ bg; - base[2] = (-((bits >> 5) & 1) & fg) ^ bg; - base[3] = (-((bits >> 4) & 1) & fg) ^ bg; - base[4] = (-((bits >> 3) & 1) & fg) ^ bg; - base[5] = (-((bits >> 2) & 1) & fg) ^ bg; - base[6] = (-((bits >> 1) & 1) & fg) ^ bg; - base[7] = (-(bits & 1) & fg) ^ bg; - base = (unsigned long *) ((char *)base + rb); - } -} - -static void __pmac -draw_byte_16(unsigned char *font, unsigned long *base, int rb) -{ - int l, bits; - int fg = 0xFFFFFFFFUL; - int bg = 0x00000000UL; - unsigned long offset = reloc_offset(); - unsigned long *eb = RELOC(expand_bits_16); - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (eb[bits >> 6] & fg) ^ bg; - base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; - base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; - base[3] = (eb[bits & 3] & fg) ^ bg; - base = (unsigned long *) ((char *)base + rb); - } -} - -static void __pmac -draw_byte_8(unsigned char *font, unsigned long *base, int rb) -{ - int l, bits; - int fg = 0x0F0F0F0FUL; - int bg = 0x00000000UL; - unsigned long offset = reloc_offset(); - unsigned long *eb = RELOC(expand_bits_8); - - for (l = 0; l < 16; ++l) - { - bits = *font++; - base[0] = (eb[bits >> 4] & fg) ^ bg; - base[1] = (eb[bits & 0xf] & fg) ^ bg; - base = (unsigned long *) ((char *)base + rb); - } -} - -static unsigned char vga_font[cmapsz] __pmacdata = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, -}; - -#endif /* CONFIG_BOOTX_TEXT */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.4.9/linux/arch/ppc/kernel/setup.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/setup.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.setup.c 1.46 07/26/01 14:18:18 trini + * BK Id: SCCS/s.setup.c 1.55 08/24/01 20:07:37 paulus */ /* * Common prep/pmac/chrp boot and setup code. @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_8xx #include #include @@ -40,55 +41,18 @@ #include #endif #include +#include #include #include #include +#include - -extern void apus_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void chrp_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void gemini_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void m8xx_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void m8260_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void pmac_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void prep_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - +extern void platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); extern void bootx_init(unsigned long r4, unsigned long phys); extern unsigned long reloc_offset(void); +extern void identify_cpu(unsigned long offset, unsigned long cpu); +extern void do_cpu_ftr_fixups(unsigned long offset); #ifdef CONFIG_XMON extern void xmon_map_scc(void); @@ -98,6 +62,13 @@ char saved_command_line[256]; unsigned char aux_device_present; struct ide_machdep_calls ppc_ide_md; +char *sysmap; +unsigned long sysmap_size; + +/* Used with the BI_MEMSIZE bootinfo parameter to store the memory + size value reported by the boot loader. */ +unsigned int boot_mem_size; + int parse_bootinfo(void); unsigned long ISA_DMA_THRESHOLD; @@ -105,7 +76,13 @@ #ifdef CONFIG_ALL_PPC int _machine = 0; -int have_of = 0; + +extern void prep_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); +extern void pmac_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); +extern void chrp_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7); #endif /* CONFIG_ALL_PPC */ #ifdef CONFIG_MAGIC_SYSRQ @@ -126,15 +103,7 @@ int icache_bsize; int ucache_bsize; -/* - * Perhaps we can put the pmac screen_info[] here - * on pmac as well so we don't need the ifdef's. - * Until we get multiple-console support in here - * that is. -- Cort - * Maybe tie it to serial consoles, since this is really what - * these processors use on existing boards. -- Dan - */ -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260) +#ifdef CONFIG_VGA_CONSOLE struct screen_info screen_info = { 0, 25, /* orig-x, orig-y */ 0, /* unused */ @@ -146,35 +115,7 @@ 1, /* orig-video-isVGA */ 16 /* orig-video-points */ }; - -/* - * I really need to add multiple-console support... -- Cort - */ -int __init pmac_display_supported(char *name) -{ - return 0; -} -void __init pmac_find_display(void) -{ -} - -#else /* CONFIG_4xx || CONFIG_8xx */ - -/* We need this to satisfy some external references until we can - * strip the kernel down. - */ -struct screen_info screen_info = { - 0, 25, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 80, /* orig-video-cols */ - 0,0,0, /* ega_ax, ega_bx, ega_cx */ - 25, /* orig-video-lines */ - 0, /* orig-video-isVGA */ - 16 /* orig-video-points */ -}; -#endif /* !CONFIG_4xx && !CONFIG_8xx */ +#endif /* CONFIG_VGA_CONSOLE */ void machine_restart(char *cmd) { @@ -190,35 +131,11 @@ { ppc_md.halt(); } - -unsigned long cpu_temp(void) -{ - unsigned char thres = 0; - -#if 0 - /* disable thrm2 */ - _set_THRM2( 0 ); - /* threshold 0 C, tid: exceeding threshold, tie: don't generate interrupt */ - _set_THRM1( THRM1_V ); - - /* we need 20us to do the compare - assume 300MHz processor clock */ - _set_THRM3(0); - _set_THRM3(THRM3_E | (300*30)<<18 ); - - udelay(100); - /* wait for the compare to complete */ - /*while ( !(_get_THRM1() & THRM1_TIV) ) ;*/ - if ( !(_get_THRM1() & THRM1_TIV) ) - printk("no tiv\n"); - if ( _get_THRM1() & THRM1_TIN ) - printk("crossed\n"); - /* turn everything off */ - _set_THRM3(0); - _set_THRM1(0); -#endif - - return thres; -} + +#ifdef CONFIG_TAU +extern u32 cpu_temp(unsigned long cpu); +extern u32 cpu_temp_both(unsigned long cpu); +#endif /* CONFIG_TAU */ int get_cpuinfo(char *buffer) { @@ -227,7 +144,7 @@ unsigned long i; unsigned int pvr; unsigned short maj, min; - + #ifdef CONFIG_SMP #define CPU_PRESENT(x) (cpu_callin_map[(x)]) #define GET_PVR ((long int)(cpu_data[i].pvr)) @@ -235,7 +152,7 @@ #else #define CPU_PRESENT(x) ((x)==0) #define smp_num_cpus 1 -#define GET_PVR ((long int)_get_PVR()) +#define GET_PVR (mfspr(PVR)) #define CD(x) (x) #endif @@ -249,90 +166,31 @@ len += sprintf(len+buffer,"cpu\t\t: "); pvr = GET_PVR; - - switch (PVR_VER(pvr)) - { - case 0x0001: - len += sprintf(len+buffer, "601\n"); - break; - case 0x0003: - len += sprintf(len+buffer, "603\n"); - break; - case 0x0004: - len += sprintf(len+buffer, "604\n"); - break; - case 0x0006: - len += sprintf(len+buffer, "603e\n"); - break; - case 0x0007: - len += sprintf(len+buffer, "603"); - if (((pvr >> 12) & 0xF) == 1) { - pvr ^= 0x00001000; /* revision fix-up */ - len += sprintf(len+buffer, "r\n"); - } else { - len += sprintf(len+buffer, "ev\n"); - } - break; - case 0x0008: /* 740/750(P) */ - case 0x1008: - len += sprintf(len+buffer, "750%s\n", - PVR_VER(pvr) == 0x1008 ? "P" : ""); - len += sprintf(len+buffer, "temperature \t: %lu C\n", - cpu_temp()); - break; - case 0x0009: /* 604e/604r */ - case 0x000A: - len += sprintf(len+buffer, "604"); - - if (PVR_VER(pvr) == 0x000A || - ((pvr >> 12) & 0xF) != 0) { - pvr &= ~0x00003000; /* revision fix-up */ - len += sprintf(len+buffer, "r\n"); - } else { - len += sprintf(len+buffer, "e\n"); - } - break; - case 0x000C: - len += sprintf(len+buffer, "7400 (G4"); + + if (cur_cpu_spec[i]->pvr_mask) + len += sprintf(len+buffer, "%s", cur_cpu_spec[i]->cpu_name); + else + len += sprintf(len+buffer, "unknown (%08x)", pvr); #ifdef CONFIG_ALTIVEC + if (cur_cpu_spec[i]->cpu_features & CPU_FTR_ALTIVEC) len += sprintf(len+buffer, ", altivec supported"); -#endif /* CONFIG_ALTIVEC */ - len += sprintf(len+buffer, ")\n"); - break; - case 0x0020: - len += sprintf(len+buffer, "403G"); - switch ((pvr >> 8) & 0xFF) { - case 0x02: - len += sprintf(len+buffer, "C\n"); - break; - case 0x14: - len += sprintf(len+buffer, "CX\n"); - break; - } - break; - case 0x0035: - len += sprintf(len+buffer, "POWER4\n"); - break; - case 0x0040: - len += sprintf(len+buffer, "POWER3 (630)\n"); - break; - case 0x0041: - len += sprintf(len+buffer, "POWER3 (630+)\n"); - break; - case 0x0050: - len += sprintf(len+buffer, "8xx\n"); - break; - case 0x0081: - len += sprintf(len+buffer, "82xx\n"); - break; - case 0x4011: - len += sprintf(len+buffer, "405GP\n"); - break; - default: - len += sprintf(len+buffer, "unknown (%08x)\n", pvr); - break; +#endif + len += sprintf(len+buffer, "\n"); +#ifdef CONFIG_TAU + if (cur_cpu_spec[i]->cpu_features & CPU_FTR_TAU) { +#ifdef CONFIG_TAU_AVERAGE /* more straightforward, but potentially misleading */ + len += sprintf(len+buffer, "temperature \t: %u C (uncalibrated)\n", + cpu_temp(i)); +#else + /* show the actual temp sensor range */ + u32 temp; + temp = cpu_temp_both(i); + len += sprintf(len+buffer, "temperature \t: %u-%u C (uncalibrated)\n", + temp & 0xff, temp >> 16); +#endif } - +#endif + /* * Assume here that all clock rates are the same in a * smp system. -- Cort @@ -394,7 +252,7 @@ } #ifdef CONFIG_SMP - if ( i ) + if ( i && smp_num_cpus > 1) len += sprintf(buffer+len, "\n"); len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n", bogosum/(500000/HZ), @@ -423,31 +281,6 @@ return len; } -#ifdef CONFIG_ALL_PPC -void __init -intuit_machine_type(void) -{ - char *model; - struct device_node *root; - - /* ask the OF info if we're a chrp or pmac */ - root = find_path_device("/"); - if (root != 0) { - /* assume pmac unless proven to be chrp -- Cort */ - _machine = _MACH_Pmac; - model = get_property(root, "device_type", NULL); - if (model && !strncmp("chrp", model, 4)) - _machine = _MACH_chrp; - else { - model = get_property(root, "model", NULL); - if (model && !strncmp(model, "IBM", 3)) - _machine = _MACH_chrp; - } - } -} -#endif /* CONFIG_ALL_PPC */ - -#if defined(CONFIG_6xx) || defined(CONFIG_PPC64BRIDGE) /* * We're called here very early in the boot. We determine the machine * type and call the appropriate low-level setup functions. @@ -472,6 +305,13 @@ * caches on yet */ memset_io(PTRRELOC(&__bss_start), 0, &_end - &__bss_start); + /* + * Identify the CPU type and fix up code sections + * that depend on which cpu we have. + */ + identify_cpu(offset, 0); + do_cpu_ftr_fixups(offset); + #if defined(CONFIG_ALL_PPC) /* If we came here from BootX, clear the screen, * set up some pointers and return. */ @@ -493,78 +333,105 @@ return phys; } -#endif /* CONFIG_6xx || CONFIG_PPC64BRIDGE */ + +#ifdef CONFIG_ALL_PPC +void __init +intuit_machine_type(void) +{ + char *model; + struct device_node *root; + + /* ask the OF info if we're a chrp or pmac */ + root = find_path_device("/"); + if (root != 0) { + /* assume pmac unless proven to be chrp -- Cort */ + _machine = _MACH_Pmac; + model = get_property(root, "device_type", NULL); + if (model && !strncmp("chrp", model, 4)) + _machine = _MACH_chrp; + else { + model = get_property(root, "model", NULL); + if (model && !strncmp(model, "IBM", 3)) + _machine = _MACH_chrp; + } + } +} /* - * Find out what kind of machine we're on and save any data we need - * from the early boot process (devtree is copied on pmac by prom_init() ) + * The ALL_PPC version of platform_init... */ -unsigned long __init -identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) { -#ifdef CONFIG_CMDLINE - strcpy(cmd_line, CONFIG_CMDLINE); -#endif /* CONFIG_CMDLINE */ +#ifdef CONFIG_BOOTX_TEXT + extern boot_infos_t *disp_bi; - parse_bootinfo(); + if (disp_bi) { + btext_clearscreen(); + btext_welcome(disp_bi); + } +#endif - if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); - -#ifdef CONFIG_ALL_PPC /* if we didn't get any bootinfo telling us what we are... */ - if ( _machine == 0 ) - { + if (_machine == 0) { /* prep boot loader tells us if we're prep or not */ if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) - { _machine = _MACH_prep; - } else - have_of = 1; } - if ( have_of ) - { - /* prom_init has already been called from __start */ - if (boot_infos) - relocate_nodes(); - /* we need to set _machine before calling finish_device_tree */ - if (_machine == 0) - intuit_machine_type(); - finish_device_tree(); - /* - * If we were booted via quik, r3 points to the physical - * address of the command-line parameters. - * If we were booted from an xcoff image (i.e. netbooted or - * booted from floppy), we get the command line from the - * bootargs property of the /chosen node. - * If an initial ramdisk is present, r3 and r4 - * are used for initrd_start and initrd_size, - * otherwise they contain 0xdeadbeef. - */ - if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { - strncpy(cmd_line, (char *)r3 + KERNELBASE, + /* not much more to do here, if prep */ + if (_machine == _MACH_prep) { + prep_init(r3, r4, r5, r6, r7); + return; + } + + /* prom_init has already been called from __start */ + if (boot_infos) + relocate_nodes(); + + /* If we aren't PReP, we can find out if we're Pmac + * or CHRP with this. */ + if (_machine == 0) + intuit_machine_type(); + + /* finish_device_tree may need _machine defined. */ + finish_device_tree(); + + /* + * If we were booted via quik, r3 points to the physical + * address of the command-line parameters. + * If we were booted from an xcoff image (i.e. netbooted or + * booted from floppy), we get the command line from the + * bootargs property of the /chosen node. + * If an initial ramdisk is present, r3 and r4 + * are used for initrd_start and initrd_size, + * otherwise they contain 0xdeadbeef. + */ + if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { + cmd_line[0] = 0; + strncpy(cmd_line, (char *)r3 + KERNELBASE, + sizeof(cmd_line)); + } else if (boot_infos != 0) { + /* booted by BootX - check for ramdisk */ + if (boot_infos->kernelParamsOffset != 0) + strncpy(cmd_line, (char *) boot_infos + + boot_infos->kernelParamsOffset, sizeof(cmd_line)); - } else if (boot_infos != 0) { - /* booted by BootX - check for ramdisk */ - if (boot_infos->kernelParamsOffset != 0) - strncpy(cmd_line, (char *) boot_infos - + boot_infos->kernelParamsOffset, - sizeof(cmd_line)); #ifdef CONFIG_BLK_DEV_INITRD - if (boot_infos->ramDisk) { - initrd_start = (unsigned long) boot_infos - + boot_infos->ramDisk; - initrd_end = initrd_start + boot_infos->ramDiskSize; - initrd_below_start_ok = 1; - } + if (boot_infos->ramDisk) { + initrd_start = (unsigned long) boot_infos + + boot_infos->ramDisk; + initrd_end = initrd_start + boot_infos->ramDiskSize; + initrd_below_start_ok = 1; + } #endif - } else { - struct device_node *chosen; - char *p; + } else { + struct device_node *chosen; + char *p; #ifdef CONFIG_BLK_DEV_INITRD - if (r3 && r4 && r4 != 0xdeadbeef) + if (r3 && r4 && r4 != 0xdeadbeef) { if (r3 < KERNELBASE) r3 += KERNELBASE; @@ -574,92 +441,32 @@ initrd_below_start_ok = 1; } #endif - chosen = find_devices("chosen"); - if (chosen != NULL) { - p = get_property(chosen, "bootargs", NULL); - if (p && *p) { - cmd_line[0] = 0; - strncpy(cmd_line, p, sizeof(cmd_line)); - } + chosen = find_devices("chosen"); + if (chosen != NULL) { + p = get_property(chosen, "bootargs", NULL); + if (p && *p) { + cmd_line[0] = 0; + strncpy(cmd_line, p, sizeof(cmd_line)); } } - cmd_line[sizeof(cmd_line) - 1] = 0; } -#endif /* CONFIG_ALL_PPC */ + cmd_line[sizeof(cmd_line) - 1] = 0; -#if defined(CONFIG_ALL_PPC) - switch (_machine) - { + switch (_machine) { case _MACH_Pmac: - pmac_init(r3, r4, r5, r6, r7); - break; - case _MACH_prep: - prep_init(r3, r4, r5, r6, r7); + pmac_init(r3, r4, r5, r6, r7); break; case _MACH_chrp: - chrp_init(r3, r4, r5, r6, r7); + chrp_init(r3, r4, r5, r6, r7); break; - default: - printk("Unknown machine type in identify_machine!\n"); - } -#elif defined(CONFIG_APUS) - apus_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_GEMINI) - gemini_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_4xx) - oak_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_8xx) - m8xx_init(r3, r4, r5, r6, r7); -#elif defined(CONFIG_8260) - m8260_init(r3, r4, r5, r6, r7); -#else -#error "No board type has been defined for identify_machine()!" -#endif - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260) - /* Check for nobats option (used in mapin_ram). */ - if (strstr(cmd_line, "nobats")) { - extern int __map_without_bats; - __map_without_bats = 1; - } -#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_8260 */ - - /* 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; } - - /* this is for modules since _machine can be a define -- Cort */ - ppc_md.ppc_machine = _machine; - - if ( ppc_md.progress ) ppc_md.progress("id mach(): done", 0x200); - - return 0; } +#endif /* CONFIG_ALL_PPC */ int parse_bootinfo(void) { 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 ) @@ -696,20 +503,43 @@ #ifdef CONFIG_ALL_PPC case BI_MACHTYPE: _machine = data[0]; - have_of = data[1]; break; #endif /* CONFIG_ALL_PPC */ + case BI_MEMSIZE: + boot_mem_size = data[0]; + break; } } return 0; } +/* + * Find out what kind of machine we're on and save any data we need + * from the early boot process (devtree is copied on pmac by prom_init()). + * This is called very early on the boot process, after a minimal + * MMU environment has been set up but before MMU_init is called. + */ +void __init +machine_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ +#ifdef CONFIG_CMDLINE + strcpy(cmd_line, CONFIG_CMDLINE); +#endif /* CONFIG_CMDLINE */ + + parse_bootinfo(); + + platform_init(r3, r4, r5, r6, r7); + + if (ppc_md.progress) + ppc_md.progress("id mach(): done", 0x200); +} + /* Checks "l2cr=xxxx" command-line option */ -int ppc_setup_l2cr(char *str) +int __init ppc_setup_l2cr(char *str) { - if ( ((_get_PVR() >> 16) == 8) || ((_get_PVR() >> 16) == 12) ) - { + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) { unsigned long val = simple_strtoul(str, NULL, 0); printk(KERN_INFO "l2cr set to %lx\n", val); _set_L2CR(0); /* force invalidate by disable cache */ @@ -761,18 +591,13 @@ * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = icache_bsize = 32; /* most common value */ - switch (_get_PVR() >> 16) { - case 1: /* 601, with unified cache */ - ucache_bsize = 32; - break; - /* XXX need definitions in here for 8xx etc. */ - case 0x40: - case 0x41: - case 0x35: /* 64-bit POWER3, POWER3+, POWER4 */ - dcache_bsize = icache_bsize = 128; - break; - } + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPLIT_ID_CACHE) { + dcache_bsize = cur_cpu_spec[0]->dcache_bsize; + icache_bsize = cur_cpu_spec[0]->icache_bsize; + ucache_bsize = 0; + } else + ucache_bsize = dcache_bsize = icache_bsize + = cur_cpu_spec[0]->dcache_bsize; /* reboot on panic */ panic_timeout = 180; @@ -813,6 +638,9 @@ paging_init(); sort_exception_table(); + + /* this is for modules since _machine can be a define -- Cort */ + ppc_md.ppc_machine = _machine; } /* Convert the shorts/longs in hd_driveid from little to big endian; diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S --- v2.4.9/linux/arch/ppc/kernel/sleep.S Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/sleep.S Tue Aug 28 06:58:33 2001 @@ -1,10 +1,10 @@ /* - * BK Id: SCCS/s.sleep.S 1.10 06/28/01 15:50:17 paulus + * BK Id: SCCS/s.sleep.S 1.13 08/19/01 22:23:04 paulus */ /* * This file contains sleep low-level functions for PowerBook G3. * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) - * and Paul Mackerras (paulus@cs.anu.edu.au). + * and Paul Mackerras (paulus@samba.org). * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -45,7 +45,13 @@ #define tovirt(rd,rs) addis rd,rs,KERNELBASE@h .text + .align 5 +/* This gets called by via-pmu.c late during the sleep process. + * The PMU was already send the sleep command and will shut us down + * soon. We need to save all that is needed and setup the wakeup + * vector that will be called by the ROM on wakeup + */ _GLOBAL(low_sleep_handler) mflr r0 stw r0,4(r1) @@ -53,13 +59,14 @@ stw r2,SL_R2(r1) stmw r12,SL_R12(r1) - /* Save MSR, SDR1, TB */ + /* Save MSR & SDR1 */ mfmsr r4 stw r4,SL_MSR(r1) mfsdr1 r4 stw r4,SL_SDR1(r1) -1: - mftbu r4 + + /* Get a stable timebase and save it */ +1: mftbu r4 stw r4,SL_TB(r1) mftb r5 stw r5,SL_TB+4(r1) @@ -114,10 +121,19 @@ /* Save HID0 */ mfspr r4,HID0 stw r4,SL_HID0(r1) - - /* Set up stuff at address 0 */ - lis r5,wake_up@ha - addi r5,r5,wake_up@l + + /* The ROM can wake us up via 2 different vectors: + * - On wallstreet & lombard, we must write a magic + * value 'Lars' at address 4 and a pointer to a + * memory location containing the PC to resume from + * at address 0. + * - On Core99, we must store the wakeup vector at + * address 0x80 and eventually it's parameters + * at address 0x84. I've have some trouble with those + * parameters however and I no longer use them. + */ + lis r5,grackle_wake_up@ha + addi r5,r5,grackle_wake_up@l tophys(r5,r5) stw r5,SL_PC(r1) lis r4,KERNELBASE@h @@ -127,22 +143,35 @@ addi r6,r6,MAGIC@l stw r5,0(r4) stw r6,4(r4) + /* Setup stuffs at 0x80-0x84 for Core99 */ + lis r3,core99_wake_up@ha + addi r3,r3,core99_wake_up@l + tophys(r3,r3) + stw r3,0x80(r4) + stw r5,0x84(r4) + /* Store a pointer to our backup storage into + * a kernel global + */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + stw r5,0(r3) + /* - * Flush the L1 data cache by reading the first 64kB of RAM + * Flush the L1 data cache by reading the first 128kB of RAM * and then flushing the same area with the dcbf instruction. * The L2 cache has already been disabled. */ - li r4,0x0800 /* 64kB / 32B */ + li r4,0x1000 /* 128kB / 32B */ mtctr r4 lis r4,KERNELBASE@h 1: lwz r0,0(r4) - addi r4,r4,0x0020 /* Go to start of next cache line */ + addi r4,r4,0x0020 /* Go to start of next cache line */ bdnz 1b sync - li r4,0x0800 /* 64k */ + li r4,0x1000 /* 128kB / 32B */ mtctr r4 lis r4,KERNELBASE@h 1: @@ -160,7 +189,13 @@ sync mtspr HID0,r2 sync - + +/* This loop puts us back to sleep in case we have a spurrious + * wakeup so that the host bridge properly stays asleep. The + * CPU will be turned off, either after a known time (about 1 + * second) on wallstreet & lombard, or as soon as the CPU enters + * SLEEP mode on core99 + */ mfmsr r2 oris r2,r2,MSR_POW@h 1: sync @@ -170,22 +205,66 @@ /* * Here is the resume code. + */ + + +/* + * Core99 machines resume here + * r4 has the physical address of SL_PC(sp) (unused) + */ +_GLOBAL(core99_wake_up) + /* Make sure HID0 no longer contains any sleep bit */ + mfspr r3,HID0 + rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ + mtspr HID0,r3 + sync + isync + + /* Won't that cause problems on CPU that doesn't support it ? */ + lis r3, 0 + mtspr SPRN_MMCR0, r3 + + /* sanitize MSR */ + mfmsr r3 + ori r3,r3,MSR_EE|MSR_IP + xori r3,r3,MSR_EE|MSR_IP + sync + isync + mtmsr r3 + sync + isync + + /* Recover sleep storage */ + lis r3,sleep_storage@ha + addi r3,r3,sleep_storage@l + tophys(r3,r3) + lwz r1,0(r3) + + /* Pass thru to older resume code ... */ +/* + * Here is the resume code for older machines. * r1 has the physical address of SL_PC(sp). */ -wake_up: - /* Flash inval the instruction cache */ +grackle_wake_up: + /* Enable and then Flash inval the instruction & data cache */ mfspr r3,HID0 - ori r3,r3, HID0_ICFI - mtspr HID0,r3 + ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI + sync isync - /* Restore the HID0 register. This turns on the L1 caches. */ + mtspr HID0,r3 + xori r3,r3, HID0_ICFI|HID0_DCI + mtspr HID0,r3 + sync + + /* Restore the remaining bits of the HID0 register. */ subi r1,r1,SL_PC lwz r3,SL_HID0(r1) sync isync mtspr HID0,r3 sync + isync /* Restore the kernel's segment registers, the BATs, and SDR1. Then we can turn on the MMU. */ @@ -242,6 +321,13 @@ lwz r4,SL_IBAT3+4(r1) mtibatl 3,r4 + /* Flush all TLBs */ + lis r4,0x1000 +1: addic. r4,r4,-0x1000 + tlbie r4 + blt 1b + sync + /* restore the MSR and turn on the MMU */ lwz r3,SL_MSR(r1) bl turn_on_mmu @@ -250,6 +336,8 @@ tovirt(r1,r1) /* Restore TB */ + li r3,0 + mttbl r3 lwz r3,SL_TB(r1) lwz r4,SL_TB+4(r1) mttbu r3 @@ -269,4 +357,10 @@ mtsrr0 r4 mtsrr1 r3 sync + isync rfi + + .data + .globl sleep_storage +sleep_storage: + .long 0 diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.4.9/linux/arch/ppc/kernel/smp.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/smp.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.smp.c 1.25 05/23/01 00:38:42 cort + * BK Id: SCCS/s.smp.c 1.29 08/20/01 21:35:14 paulus */ /* * Smp support for ppc. @@ -9,11 +9,6 @@ * * Copyright (C) 1999 Cort Dougan * - * Support for PReP (Motorola MTX/MVME) and Macintosh G4 SMP - * by Troy Benjegerdes (hozer@drgw.net) - * - * Support for DayStar quad CPU cards - * Copyright (C) XLR8, Inc. 1994-2000 */ #include @@ -43,9 +38,9 @@ #include #include #include -#include #include "open_pic.h" + int smp_threads_ready; volatile int smp_commenced; int smp_num_cpus = 1; @@ -54,13 +49,14 @@ struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 }; atomic_t ipi_recv; atomic_t ipi_sent; -spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; +spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED; unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; cycles_t cacheflush_time; static int max_cpus __initdata = NR_CPUS; unsigned long cpu_online_map; int smp_hw_index[NR_CPUS]; +static struct smp_ops_t *smp_ops; /* all cpu mappings are 1-1 -- Cort */ volatile unsigned long cpu_callin_map[NR_CPUS]; @@ -74,60 +70,6 @@ void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -extern void __secondary_start_psurge(void); -extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ -extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ - -/* Addresses for powersurge registers */ -#define HAMMERHEAD_BASE 0xf8000000 -#define HHEAD_CONFIG 0x90 -#define HHEAD_SEC_INTR 0xc0 - -/* register for interrupting the primary processor on the powersurge */ -/* N.B. this is actually the ethernet ROM! */ -#define PSURGE_PRI_INTR 0xf3019000 - -/* register for storing the start address for the secondary processor */ -/* N.B. this is the PCI config space address register for the 1st bridge */ -#define PSURGE_START 0xf2800000 - -/* Daystar/XLR8 4-CPU card */ -#define PSURGE_QUAD_REG_ADDR 0xf8800000 - -#define PSURGE_QUAD_IRQ_SET 0 -#define PSURGE_QUAD_IRQ_CLR 1 -#define PSURGE_QUAD_IRQ_PRIMARY 2 -#define PSURGE_QUAD_CKSTOP_CTL 3 -#define PSURGE_QUAD_PRIMARY_ARB 4 -#define PSURGE_QUAD_BOARD_ID 6 -#define PSURGE_QUAD_WHICH_CPU 7 -#define PSURGE_QUAD_CKSTOP_RDBK 8 -#define PSURGE_QUAD_RESET_CTL 11 - -#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) -#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) -#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) -#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) - -/* virtual addresses for the above */ -static volatile u8 *hhead_base; -static volatile u8 *quad_base; -static volatile u32 *psurge_pri_intr; -static volatile u8 *psurge_sec_intr; -static volatile u32 *psurge_start; - -/* what sort of powersurge board we have */ -static int psurge_type; - -/* values for psurge_type */ -#define PSURGE_DUAL 0 -#define PSURGE_QUAD_OKEE 1 -#define PSURGE_QUAD_COTTON 2 -#define PSURGE_QUAD_ICEGRASS 3 - -/* l2 cache stuff for dual G4 macs */ -extern void core99_init_l2(void); - /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. * * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up @@ -137,621 +79,12 @@ #define PPC_MSG_INVALIDATE_TLB 2 #define PPC_MSG_XMON_BREAK 3 -static inline void set_tb(unsigned int upper, unsigned int lower) -{ - mtspr(SPRN_TBWL, 0); - mtspr(SPRN_TBWU, upper); - mtspr(SPRN_TBWL, lower); -} - -/* - * Set and clear IPIs for powersurge. - */ -static inline void psurge_set_ipi(int cpu) -{ - if (cpu == 0) - in_be32(psurge_pri_intr); - else if (psurge_type == PSURGE_DUAL) - out_8(psurge_sec_intr, 0); - else - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); -} - -static inline void psurge_clr_ipi(int cpu) -{ - if (cpu > 0) { - if (psurge_type == PSURGE_DUAL) - out_8(psurge_sec_intr, ~0); - else - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); - } -} - -/* - * On powersurge (old SMP powermac architecture) we don't have - * separate IPIs for separate messages like openpic does. Instead - * we have a bitmap for each processor, where a 1 bit means that - * the corresponding message is pending for that processor. - * Ideally each cpu's entry would be in a different cache line. - * -- paulus. - */ -static unsigned long psurge_smp_message[NR_CPUS]; - -void psurge_smp_message_recv(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int msg; - - /* clear interrupt */ - psurge_clr_ipi(cpu); - - if (smp_num_cpus < 2) - return; - - /* make sure there is a message there */ - for (msg = 0; msg < 4; msg++) - if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) - smp_message_recv(msg, regs); -} - -void -psurge_primary_intr(int irq, void *d, struct pt_regs *regs) -{ - psurge_smp_message_recv(regs); -} - -static void -smp_psurge_message_pass(int target, int msg, unsigned long data, int wait) -{ - int i; - - if (smp_num_cpus < 2) - return; - - for (i = 0; i < smp_num_cpus; i++) { - if (target == MSG_ALL - || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) - || target == i) { - set_bit(msg, &psurge_smp_message[i]); - psurge_set_ipi(i); - } - } -} - -/* - * Determine a quad card presence. We read the board ID register, we - * force the data bus to change to something else, and we read it again. - * It it's stable, then the register probably exist (ugh !) - */ -static int __init psurge_quad_probe(void) -{ - int type; - unsigned int i; - - type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); - if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS - || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) - return PSURGE_DUAL; - - /* looks OK, try a slightly more rigorous test */ - /* bogus is not necessarily cacheline-aligned, - though I don't suppose that really matters. -- paulus */ - for (i = 0; i < 100; i++) { - volatile u32 bogus[8]; - bogus[(0+i)%8] = 0x00000000; - bogus[(1+i)%8] = 0x55555555; - bogus[(2+i)%8] = 0xFFFFFFFF; - bogus[(3+i)%8] = 0xAAAAAAAA; - bogus[(4+i)%8] = 0x33333333; - bogus[(5+i)%8] = 0xCCCCCCCC; - bogus[(6+i)%8] = 0xCCCCCCCC; - bogus[(7+i)%8] = 0x33333333; - wmb(); - asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); - mb(); - if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) - return PSURGE_DUAL; - } - return type; -} - -static void __init psurge_quad_init(void) -{ - int procbits; - - if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); - procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); - if (psurge_type == PSURGE_QUAD_ICEGRASS) - PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); - else - PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); - mdelay(33); - out_8(psurge_sec_intr, ~0); - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); - PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); - if (psurge_type != PSURGE_QUAD_ICEGRASS) - PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); - PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); - mdelay(33); - PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); - mdelay(33); - PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); - mdelay(33); -} - -static int __init smp_psurge_probe(void) -{ - int i, ncpus; - - /* We don't do SMP on the PPC601 -- paulus */ - if ((_get_PVR() >> 16) == 1) - return 1; - - /* - * The powersurge cpu board can be used in the generation - * of powermacs that have a socket for an upgradeable cpu card, - * including the 7500, 8500, 9500, 9600. - * The device tree doesn't tell you if you have 2 cpus because - * OF doesn't know anything about the 2nd processor. - * Instead we look for magic bits in magic registers, - * in the hammerhead memory controller in the case of the - * dual-cpu powersurge board. -- paulus. - */ - if (find_devices("hammerhead") == NULL) - return 1; - - hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); - quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); - psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; - - psurge_type = psurge_quad_probe(); - if (psurge_type != PSURGE_DUAL) { - psurge_quad_init(); - /* All released cards using this HW design have 4 CPUs */ - ncpus = 4; - } else { - iounmap((void *) quad_base); - if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { - /* not a dual-cpu card */ - iounmap((void *) hhead_base); - return 1; - } - ncpus = 2; - } - - psurge_start = ioremap(PSURGE_START, 4); - psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); - - /* this is not actually strictly necessary -- paulus. */ - for (i = 1; i < ncpus; ++i) - smp_hw_index[i] = i; - - if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); - - return ncpus; -} - -static void __init smp_psurge_kick_cpu(int nr) -{ - void (*start)(void) = __secondary_start_psurge; - - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); - - /* setup entry point of secondary processor */ - switch (nr) { - case 2: - start = __secondary_start_psurge2; - break; - case 3: - start = __secondary_start_psurge3; - break; - } - - out_be32(psurge_start, __pa(start)); - mb(); - - psurge_set_ipi(nr); - udelay(10); - psurge_clr_ipi(nr); - - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); -} - -/* - * With the dual-cpu powersurge board, the decrementers and timebases - * of both cpus are frozen after the secondary cpu is started up, - * until we give the secondary cpu another interrupt. This routine - * uses this to get the timebases synchronized. - * -- paulus. - */ -static void __init psurge_dual_sync_tb(int cpu_nr) -{ - static volatile int sec_tb_reset = 0; - int t; - - set_dec(tb_ticks_per_jiffy); - set_tb(0, 0); - last_jiffy_stamp(cpu_nr) = 0; - - if (cpu_nr > 0) { - mb(); - sec_tb_reset = 1; - return; - } - - /* wait for the secondary to have reset its TB before proceeding */ - for (t = 10000000; t > 0 && !sec_tb_reset; --t) - ; - - /* now interrupt the secondary, starting both TBs */ - psurge_set_ipi(1); - - smp_tb_synchronized = 1; -} - -static void -smp_psurge_setup_cpu(int cpu_nr) -{ - - if (cpu_nr == 0) { - if (smp_num_cpus < 2) - return; - /* reset the entry point so if we get another intr we won't - * try to startup again */ - out_be32(psurge_start, 0x100); - if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0)) - printk(KERN_ERR "Couldn't get primary IPI interrupt"); - } - - if (psurge_type == PSURGE_DUAL) - psurge_dual_sync_tb(cpu_nr); -} - - -static void -smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) -{ - /* make sure we're sending something that translates to an IPI */ - if ( msg > 0x3 ){ - printk("SMP %d: smp_message_pass: unknown msg %d\n", - smp_processor_id(), msg); - return; - } - switch ( target ) - { - case MSG_ALL: - openpic_cause_IPI(msg, 0xffffffff); - break; - case MSG_ALL_BUT_SELF: - openpic_cause_IPI(msg, - 0xffffffff & ~(1 << smp_processor_id())); - break; - default: - openpic_cause_IPI(msg, 1<next) != NULL) - ++ncpus; - printk("smp_core99_probe: found %d cpus\n", ncpus); - if (ncpus > 1) { - openpic_request_IPIs(); - for (i = 1; i < ncpus; ++i) - smp_hw_index[i] = i; - } - - return ncpus; -} - -static void -smp_core99_kick_cpu(int nr) -{ - unsigned long save_vector, new_vector; - unsigned long flags; -#if 1 /* New way... */ - volatile unsigned long *vector - = ((volatile unsigned long *)(KERNELBASE+0x100)); - if (nr < 1 || nr > 3) - return; -#else - volatile unsigned long *vector - = ((volatile unsigned long *)(KERNELBASE+0x500)); - if (nr != 1) - return; -#endif - if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); - - local_irq_save(flags); - local_irq_disable(); - - /* Save reset vector */ - save_vector = *vector; - - /* Setup fake reset vector that does - * b __secondary_start_psurge - KERNELBASE - */ - switch(nr) { - case 1: - new_vector = (unsigned long)__secondary_start_psurge; - break; - case 2: - new_vector = (unsigned long)__secondary_start_psurge2; - break; - case 3: - new_vector = (unsigned long)__secondary_start_psurge3; - break; - } - *vector = 0x48000002 + new_vector - KERNELBASE; - - /* flush data cache and inval instruction cache */ - flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); - - /* Put some life in our friend */ - feature_core99_kick_cpu(nr); - - /* FIXME: We wait a bit for the CPU to take the exception, I should - * instead wait for the entry code to set something for me. Well, - * ideally, all that crap will be done in prom.c and the CPU left - * in a RAM-based wait loop like CHRP. - */ - mdelay(1); - - /* Restore our exception vector */ - *vector = save_vector; - flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); - - local_irq_restore(flags); - if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); -} - -static void -smp_core99_setup_cpu(int cpu_nr) -{ - /* Setup openpic */ - do_openpic_setup_cpu(); - - /* Setup L2 */ - if (cpu_nr != 0) - core99_init_l2(); - else - if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); -} - -static int -smp_chrp_probe(void) -{ - extern unsigned long smp_chrp_cpu_nr; - - if (smp_chrp_cpu_nr > 1) - openpic_request_IPIs(); - - return smp_chrp_cpu_nr; -} - -static void -smp_chrp_kick_cpu(int nr) -{ - *(unsigned long *)KERNELBASE = nr; - asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); -} - -static void -smp_chrp_setup_cpu(int cpu_nr) -{ - static atomic_t ready = ATOMIC_INIT(1); - static volatile int frozen = 0; - - if (cpu_nr == 0) { - /* wait for all the others */ - while (atomic_read(&ready) < smp_num_cpus) - barrier(); - atomic_set(&ready, 1); - /* freeze the timebase */ - call_rtas("freeze-time-base", 0, 1, NULL); - mb(); - frozen = 1; - /* XXX assumes this is not a 601 */ - set_tb(0, 0); - last_jiffy_stamp(0) = 0; - while (atomic_read(&ready) < smp_num_cpus) - barrier(); - /* thaw the timebase again */ - call_rtas("thaw-time-base", 0, 1, NULL); - mb(); - frozen = 0; - smp_tb_synchronized = 1; - } else { - atomic_inc(&ready); - while (!frozen) - barrier(); - set_tb(0, 0); - last_jiffy_stamp(0) = 0; - mb(); - atomic_inc(&ready); - while (frozen) - barrier(); - } - - if (OpenPIC_Addr) - do_openpic_setup_cpu(); -} - -#ifdef CONFIG_POWER4 -static void -smp_xics_message_pass(int target, int msg, unsigned long data, int wait) -{ - /* for now, only do reschedule messages - since we only have one IPI */ - if (msg != PPC_MSG_RESCHEDULE) - return; - for (i = 0; i < smp_num_cpus; ++i) { - if (target == MSG_ALL || target == i - || (target == MSG_ALL_BUT_SELF - && i != smp_processor_id())) - xics_cause_IPI(i); - } -} - -static int -smp_xics_probe(void) -{ - return smp_chrp_cpu_nr; -} - -static void -smp_xics_setup_cpu(int cpu_nr) -{ - if (cpu_nr > 0) - xics_setup_cpu(); -} -#endif /* CONFIG_POWER4 */ - -static int -smp_prep_probe(void) -{ - extern int mot_multi; - - if (mot_multi) { - openpic_request_IPIs(); - smp_hw_index[1] = 1; - return 2; - } - - return 1; -} - -static void -smp_prep_kick_cpu(int nr) -{ - extern unsigned long *MotSave_SmpIar; - extern unsigned char *MotSave_CpusState[2]; - - *MotSave_SmpIar = (unsigned long)__secondary_start_psurge - KERNELBASE; - *MotSave_CpusState[1] = CPU_GOOD; - printk("CPU1 reset, waiting\n"); -} - -static void -smp_prep_setup_cpu(int cpu_nr) -{ - if (OpenPIC_Addr) - do_openpic_setup_cpu(); -} - -#ifdef CONFIG_GEMINI -static int -smp_gemini_probe(void) -{ - int i, nr; - - nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; - if (nr == 0) - nr = 4; - - if (nr > 1) { - openpic_request_IPIs(); - for (i = 1; i < nr; ++i) - smp_hw_index[i] = i; - } - - return nr; -} - -static void -smp_gemini_kick_cpu(int nr) -{ - openpic_init_processor( 1< 0) - gemini_init_l2(); -} -#endif /* CONFIG_GEMINI */ - - -static struct smp_ops_t { - void (*message_pass)(int target, int msg, unsigned long data, int wait); - int (*probe)(void); - void (*kick_cpu)(int nr); - void (*setup_cpu)(int nr); - -} *smp_ops; - #define smp_message_pass(t,m,d,w) \ do { if (smp_ops) \ atomic_inc(&ipi_sent); \ smp_ops->message_pass((t),(m),(d),(w)); \ } while(0) - -/* PowerSurge-style Macs */ -static struct smp_ops_t psurge_smp_ops = { - smp_psurge_message_pass, - smp_psurge_probe, - smp_psurge_kick_cpu, - smp_psurge_setup_cpu, -}; - -/* Core99 Macs (dual G4s) */ -static struct smp_ops_t core99_smp_ops = { - smp_openpic_message_pass, - smp_core99_probe, - smp_core99_kick_cpu, - smp_core99_setup_cpu, -}; - -/* CHRP with openpic */ -static struct smp_ops_t chrp_smp_ops = { - smp_openpic_message_pass, - smp_chrp_probe, - smp_chrp_kick_cpu, - smp_chrp_setup_cpu, -}; - -#ifdef CONFIG_POWER4 -/* CHRP with new XICS interrupt controller */ -static struct smp_ops_t xics_smp_ops = { - smp_xics_message_pass, - smp_xics_probe, - smp_chrp_kick_cpu, - smp_xics_setup_cpu, -}; -#endif /* CONFIG_POWER4 */ - -/* PReP (MTX) */ -static struct smp_ops_t prep_smp_ops = { - smp_openpic_message_pass, - smp_prep_probe, - smp_prep_kick_cpu, - smp_prep_setup_cpu, -}; - -#ifdef CONFIG_GEMINI -/* Gemini */ -static struct smp_ops_t gemini_smp_ops = { - smp_openpic_message_pass, - smp_gemini_probe, - smp_gemini_kick_cpu, - smp_gemini_setup_cpu, -}; -#endif /* CONFIG_GEMINI */ - /* * Common functions */ @@ -798,7 +131,7 @@ */ void smp_send_tlb_invalidate(int cpu) { - if ( (_get_PVR()>>16) == 8 ) + if ( PVR_VER(mfspr(PVR)) == 8 ) smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0); } @@ -947,7 +280,6 @@ extern struct task_struct *current_set[NR_CPUS]; int i, cpu_nr; struct task_struct *p; - unsigned long a; printk("Entering SMP Mode...\n"); smp_num_cpus = 1; @@ -973,35 +305,12 @@ */ cacheflush_time = 5 * 1024; - /* To be later replaced by some arch-specific routine */ - switch(_machine) { - case _MACH_Pmac: - /* Check for Core99 */ - if (find_devices("uni-n")) - smp_ops = &core99_smp_ops; - else - smp_ops = &psurge_smp_ops; - break; - case _MACH_chrp: -#ifndef CONFIG_POWER4 - smp_ops = &chrp_smp_ops; -#else - smp_ops = &xics_smp_ops; -#endif /* CONFIG_POWER4 */ - break; - case _MACH_prep: - smp_ops = &prep_smp_ops; - break; -#ifdef CONFIG_GEMINI - case _MACH_gemini: - smp_ops = &gemini_smp_ops; - break; -#endif /* CONFIG_GEMINI */ - default: + smp_ops = ppc_md.smp_ops; + if (smp_ops == NULL) { printk("SMP not supported on this machine.\n"); return; } - + /* Probe arch for CPUs */ cpu_nr = smp_ops->probe(); @@ -1044,10 +353,12 @@ p->has_cpu = 1; current_set[i] = p; - /* need to flush here since secondary bats aren't setup */ - for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) - asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); - asm volatile("sync"); + /* + * There was a cache flush loop here to flush the cache + * to memory for the first 8MB of RAM. The cache flush + * has been pushed into the kick_cpu function for those + * platforms that need it. + */ /* wake up cpus */ smp_ops->kick_cpu(i); @@ -1155,7 +466,6 @@ /* so time.c doesn't get confused */ set_dec(tb_ticks_per_jiffy); last_jiffy_stamp(cpu) = 0; - cpu_callin_map[cpu] = 1; } void __init smp_commence(void) @@ -1247,7 +557,7 @@ /* assume bogomips are same for everything */ c->loops_per_jiffy = loops_per_jiffy; - c->pvr = _get_PVR(); + c->pvr = mfspr(PVR); } static int __init maxcpus(char *str) diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/temp.c linux/arch/ppc/kernel/temp.c --- v2.4.9/linux/arch/ppc/kernel/temp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/temp.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,278 @@ +/* + * temp.c Thermal management for cpu's with Thermal Assist Units + * + * Written by Troy Benjegerdes + * + * TODO: + * dynamic power management to limit peak CPU temp (using ICTC) + * calibration??? + * + * Silly, crazy ideas: use cpu load (from scheduler) and ICTC to extend battery + * life in portables, and add a 'performance/watt' metric somewhere in /proc + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static struct tau_temp +{ + int interrupts; + unsigned char low; + unsigned char high; + unsigned char grew; +} tau[NR_CPUS]; + +struct timer_list tau_timer; + +#undef DEBUG + +/* TODO: put these in a /proc interface, with some sanity checks, and maybe + * dynamic adjustment to minimize # of interrupts */ +/* configurable values for step size and how much to expand the window when + * we get an interrupt. These are based on the limit that was out of range */ +#define step_size 2 /* step size when temp goes out of range */ +#define window_expand 1 /* expand the window by this much */ +/* configurable values for shrinking the window */ +#define shrink_timer 2*HZ /* period between shrinking the window */ +#define min_window 2 /* minimum window size, degrees C */ + +void set_thresholds(unsigned long cpu) +{ +#ifdef CONFIG_TAU_INT + /* + * setup THRM1, + * threshold, valid bit, enable interrupts, interrupt when below threshold + */ + mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID); + + /* setup THRM2, + * threshold, valid bit, enable interrupts, interrupt when above threshhold + */ + mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE); +#else + /* same thing but don't enable interrupts */ + mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TID); + mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V); +#endif +} + +void TAUupdate(int cpu) +{ + unsigned thrm; + +#ifdef DEBUG + printk("TAUupdate "); +#endif + + /* if both thresholds are crossed, the step_sizes cancel out + * and the window winds up getting expanded twice. */ + if((thrm = mfspr(SPRN_THRM1)) & THRM1_TIV){ /* is valid? */ + if(thrm & THRM1_TIN){ /* crossed low threshold */ + if (tau[cpu].low >= step_size){ + tau[cpu].low -= step_size; + tau[cpu].high -= (step_size - window_expand); + } + tau[cpu].grew = 1; +#ifdef DEBUG + printk("low threshold crossed "); +#endif + } + } + if((thrm = mfspr(SPRN_THRM2)) & THRM1_TIV){ /* is valid? */ + if(thrm & THRM1_TIN){ /* crossed high threshold */ + if (tau[cpu].high <= 127-step_size){ + tau[cpu].low += (step_size - window_expand); + tau[cpu].high += step_size; + } + tau[cpu].grew = 1; +#ifdef DEBUG + printk("high threshold crossed "); +#endif + } + } + +#ifdef DEBUG + printk("grew = %d\n", tau[cpu].grew); +#endif + +#ifndef CONFIG_TAU_INT /* tau_timeout will do this if not using interrupts */ + set_thresholds(cpu); +#endif + +} + +#ifdef CONFIG_TAU_INT +/* + * TAU interrupts - called when we have a thermal assist unit interrupt + * with interrupts disabled + */ + +void TAUException(struct pt_regs * regs) +{ + unsigned long cpu = smp_processor_id(); + + hardirq_enter(cpu); + tau[cpu].interrupts++; + + TAUupdate(cpu); + + hardirq_exit(cpu); + return; +} +#endif /* CONFIG_TAU_INT */ + +static void tau_timeout(void * info) +{ + unsigned long cpu = smp_processor_id(); + unsigned long flags; + int size; + int shrink; + + /* disabling interrupts *should* be okay */ + save_flags(flags); cli(); + +#ifndef CONFIG_TAU_INT + TAUupdate(cpu); +#endif + + size = tau[cpu].high - tau[cpu].low; + if (size > min_window && ! tau[cpu].grew) { + /* do an exponential shrink of half the amount currently over size */ + shrink = (2 + size - min_window) / 4; + if (shrink) { + tau[cpu].low += shrink; + tau[cpu].high -= shrink; + } else { /* size must have been min_window + 1 */ + tau[cpu].low += 1; +#if 1 /* debug */ + if ((tau[cpu].high - tau[cpu].low) != min_window){ + printk(KERN_ERR "temp.c: line %d, logic error\n", __LINE__); + } +#endif + } + } + + tau[cpu].grew = 0; + + set_thresholds(cpu); + + /* + * Do the enable every time, since otherwise a bunch of (relatively) + * complex sleep code needs to be added. One mtspr every time + * tau_timeout is called is probably not a big deal. + * + * Enable thermal sensor and set up sample interval timer + * need 20 us to do the compare.. until a nice 'cpu_speed' function + * call is implemented, just assume a 500 mhz clock. It doesn't really + * matter if we take too long for a compare since it's all interrupt + * driven anyway. + * + * use a extra long time.. (60 us @ 500 mhz) + */ + mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E); + + restore_flags(flags); +} + +static void tau_timeout_smp(unsigned long unused) +{ + + /* schedule ourselves to be run again */ + mod_timer(&tau_timer, jiffies + shrink_timer) ; +#ifdef CONFIG_SMP + smp_call_function(tau_timeout, NULL, 1, 0); +#endif + tau_timeout(NULL); +} + +/* + * setup the TAU + * + * Set things up to use THRM1 as a temperature lower bound, and THRM2 as an upper bound. + * Start off at zero + */ + +int tau_initialized = 0; + +void __init TAU_init_smp(void * info) +{ + unsigned long cpu = smp_processor_id(); + + /* set these to a reasonable value and let the timer shrink the + * window */ + tau[cpu].low = 5; + tau[cpu].high = 120; + + set_thresholds(cpu); +} + +int __init TAU_init(void) +{ + /* We assume in SMP that if one CPU has TAU support, they + * all have it --BenH + */ + if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_TAU)) { + printk("Thermal assist unit not available\n"); + tau_initialized = 0; + return 1; + } + + + /* first, set up the window shrinking timer */ + init_timer(&tau_timer); + tau_timer.function = tau_timeout_smp; + tau_timer.expires = jiffies + shrink_timer; + add_timer(&tau_timer); + +#ifdef CONFIG_SMP + smp_call_function(TAU_init_smp, NULL, 1, 0); +#endif + TAU_init_smp(NULL); + + printk("Thermal assist unit "); +#ifdef CONFIG_TAU_INT + printk("using interrupts, "); +#else + printk("using timers, "); +#endif + printk("shrink_timer: %d jiffies\n", shrink_timer); + tau_initialized = 1; + + return 0; +} + +__initcall(TAU_init); + +/* + * return current temp + */ + +u32 cpu_temp_both(unsigned long cpu) +{ + return ((tau[cpu].high << 16) | tau[cpu].low); +} + +int cpu_temp(unsigned long cpu) +{ + return ((tau[cpu].high + tau[cpu].low) / 2); +} + +int tau_interrupts(unsigned long cpu) +{ + return (tau[cpu].interrupts); +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.4.9/linux/arch/ppc/kernel/time.c Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/kernel/time.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.time.c 1.18 06/06/01 22:33:09 paulus + * BK Id: SCCS/s.time.c 1.21 08/20/01 22:08:08 paulus */ /* * Common time routines among all ppc machines. @@ -72,11 +72,6 @@ unsigned long disarm_decr[NR_CPUS]; -#ifdef CONFIG_SMP -extern void smp_local_timer_interrupt(struct pt_regs *); -extern int smp_tb_synchronized; -#endif /* CONFIG_SMP */ - extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); /* keep track of when we need to update the rtc */ @@ -321,27 +316,30 @@ * makes things more complex. Repeatedly read the RTC until the * next second boundary to try to achieve some precision... */ - stamp = get_native_tbl(); - sec = ppc_md.get_rtc_time(); - elapsed = 0; - do { - old_stamp = stamp; - old_sec = sec; + if (ppc_md.get_rtc_time) { stamp = get_native_tbl(); - if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; - elapsed += stamp - old_stamp; sec = ppc_md.get_rtc_time(); - } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); - if (sec==old_sec) { - printk("Warning: real time clock seems stuck!\n"); + elapsed = 0; + do { + old_stamp = stamp; + old_sec = sec; + stamp = get_native_tbl(); + if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; + elapsed += stamp - old_stamp; + sec = ppc_md.get_rtc_time(); + } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); + if (sec==old_sec) { + printk("Warning: real time clock seems stuck!\n"); + } + write_lock_irqsave(&xtime_lock, flags); + xtime.tv_sec = sec; + last_jiffy_stamp(0) = tb_last_stamp = stamp; + xtime.tv_usec = 0; + /* No update now, we just read the time from the RTC ! */ + last_rtc_update = xtime.tv_sec; + write_unlock_irqrestore(&xtime_lock, flags); } - write_lock_irqsave(&xtime_lock, flags); - xtime.tv_sec = sec; - last_jiffy_stamp(0) = tb_last_stamp = stamp; - xtime.tv_usec = 0; - /* No update now, we just read the time from the RTC ! */ - last_rtc_update = xtime.tv_sec; - write_unlock_irqrestore(&xtime_lock, flags); + /* Not exact, but the timer interrupt takes care of this */ set_dec(tb_ticks_per_jiffy); diff -u --recursive --new-file v2.4.9/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.4.9/linux/arch/ppc/kernel/traps.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/kernel/traps.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.traps.c 1.16 07/31/01 10:53:34 trini + * BK Id: SCCS/s.traps.c 1.19 08/24/01 20:07:37 paulus */ /* * linux/arch/ppc/kernel/traps.c @@ -244,7 +244,7 @@ */ if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) { rd = (instword >> 21) & 0x1f; - regs->gpr[rd] = _get_PVR(); + regs->gpr[rd] = mfspr(PVR); retval = 0; } if (retval == 0) @@ -372,12 +372,14 @@ } #endif +#if !defined(CONFIG_TAU_INT) void TAUException(struct pt_regs *regs) { printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n", regs->nip, regs->msr, regs->trap); } +#endif /* CONFIG_INT_TAU */ void __init trap_init(void) { diff -u --recursive --new-file v2.4.9/linux/arch/ppc/lib/checksum.S linux/arch/ppc/lib/checksum.S --- v2.4.9/linux/arch/ppc/lib/checksum.S Mon May 21 17:04:47 2001 +++ linux/arch/ppc/lib/checksum.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.checksum.S 1.5 05/17/01 18:14:22 cort + * BK Id: SCCS/s.checksum.S 1.8 08/20/01 22:09:34 paulus */ /* * This file contains assembly-language implementations @@ -122,12 +122,30 @@ addc r0,r0,r6 srwi. r6,r5,2 /* # words to do */ beq 3f -1: mtctr r6 -82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */ -92: stwu r6,4(r4) /* be unnecessary to unroll this loop */ +1: srwi. r6,r5,4 /* # groups of 4 words to do */ + beq 10f + mtctr r6 +71: lwz r6,4(r3) +72: lwz r9,8(r3) +73: lwz r10,12(r3) +74: lwzu r11,16(r3) adde r0,r0,r6 +75: stw r6,4(r4) + adde r0,r0,r9 +76: stw r9,8(r4) + adde r0,r0,r10 +77: stw r10,12(r4) + adde r0,r0,r11 +78: stwu r11,16(r4) + bdnz 71b +10: rlwinm. r6,r5,30,30,31 /* # words left to do */ + beq 13f + mtctr r6 +82: lwzu r9,4(r3) +92: stwu r9,4(r4) + adde r0,r0,r9 bdnz 82b - andi. r5,r5,3 +13: andi. r5,r5,3 3: cmpi 0,r5,2 blt+ 4f 83: lhz r6,4(r3) @@ -148,12 +166,16 @@ /* These shouldn't go in the fixup section, since that would cause the ex_table addresses to get out of order. */ +src_error_4: + mfctr r6 /* update # bytes remaining from ctr */ + rlwimi r5,r6,4,0,27 + b 79f src_error_1: li r6,0 subi r5,r5,2 95: sth r6,4(r4) addi r4,r4,2 - srwi. r6,r5,2 +79: srwi. r6,r5,2 beq 3f mtctr r6 src_error_2: @@ -187,6 +209,14 @@ .section __ex_table,"a" .long 81b,src_error_1 .long 91b,dst_error + .long 71b,src_error_4 + .long 72b,src_error_4 + .long 73b,src_error_4 + .long 74b,src_error_4 + .long 75b,dst_error + .long 76b,dst_error + .long 77b,dst_error + .long 78b,dst_error .long 82b,src_error_2 .long 92b,dst_error .long 83b,src_error_3 diff -u --recursive --new-file v2.4.9/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c --- v2.4.9/linux/arch/ppc/lib/locks.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/lib/locks.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.locks.c 1.8 05/17/01 18:14:22 cort + * BK Id: SCCS/s.locks.c 1.11 08/19/01 22:27:32 paulus */ /* * Locks for smp ppc @@ -16,29 +16,53 @@ #include #include -#define DEBUG_LOCKS 1 +#ifdef SPINLOCK_DEBUG #undef INIT_STUCK #define INIT_STUCK 200000000 /*0xffffffff*/ +/* + * Try to acquire a spinlock. + * Only does the stwcx. if the load returned 0 - the Programming + * Environments Manual suggests not doing unnecessary stcwx.'s + * since they may inhibit forward progress by other CPUs in getting + * a lock. + */ +static unsigned long __spin_trylock(volatile unsigned long *lock) +{ + unsigned long ret; + + __asm__ __volatile__ ("\n\ +1: lwarx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + bne 2f\n\ + stwcx. %2,0,%1\n\ + bne- 1b\n\ + isync\n\ +2:" + : "=&r"(ret) + : "r"(lock), "r"(1) + : "cr0", "memory"); + + return ret; +} + void _spin_lock(spinlock_t *lock) { int cpu = smp_processor_id(); -#ifdef DEBUG_LOCKS unsigned int stuck = INIT_STUCK; -#endif /* DEBUG_LOCKS */ while (__spin_trylock(&lock->lock)) { -#ifdef DEBUG_LOCKS - if(!--stuck) { - printk("_spin_lock(%p) CPU#%d NIP %p" - " holder: cpu %ld pc %08lX\n", - lock, cpu, __builtin_return_address(0), - lock->owner_cpu,lock->owner_pc); - stuck = INIT_STUCK; - /* steal the lock */ - /*xchg_u32((void *)&lock->lock,0);*/ + while ((unsigned volatile long)lock->lock != 0) { + if (!--stuck) { + printk("_spin_lock(%p) CPU#%d NIP %p" + " holder: cpu %ld pc %08lX\n", + lock, cpu, __builtin_return_address(0), + lock->owner_cpu,lock->owner_pc); + stuck = INIT_STUCK; + /* steal the lock */ + /*xchg_u32((void *)&lock->lock,0);*/ + } } -#endif /* DEBUG_LOCKS */ } lock->owner_pc = (unsigned long)__builtin_return_address(0); lock->owner_cpu = cpu; @@ -53,11 +77,8 @@ return 1; } - - void _spin_unlock(spinlock_t *lp) { -#ifdef DEBUG_LOCKS if ( !lp->lock ) printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n", lp, smp_processor_id(), __builtin_return_address(0), @@ -66,13 +87,12 @@ printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n", lp, smp_processor_id(), (int)lp->owner_cpu, lp->owner_pc,lp->lock); -#endif /* DEBUG_LOCKS */ lp->owner_pc = lp->owner_cpu = 0; wmb(); lp->lock = 0; - wmb(); } + /* * Just like x86, implement read-write locks as a 32-bit counter * with the high bit (sign) being the "write" bit. @@ -80,14 +100,11 @@ */ void _read_lock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS unsigned long stuck = INIT_STUCK; int cpu = smp_processor_id(); -#endif /* DEBUG_LOCKS */ again: /* get our read lock in there */ - wmb(); atomic_inc((atomic_t *) &(rw)->lock); if ( (signed long)((rw)->lock) < 0) /* someone has a write lock */ { @@ -96,13 +113,11 @@ /* wait for the write lock to go away */ while ((signed long)((rw)->lock) < 0) { -#ifdef DEBUG_LOCKS if(!--stuck) { printk("_read_lock(%p) CPU#%d\n", rw, cpu); stuck = INIT_STUCK; } -#endif /* DEBUG_LOCKS */ } /* try to get the read lock again */ goto again; @@ -112,38 +127,30 @@ void _read_unlock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS if ( rw->lock == 0 ) printk("_read_unlock(): %s/%d (nip %08lX) lock %lx\n", current->comm,current->pid,current->thread.regs->nip, rw->lock); -#endif /* DEBUG_LOCKS */ wmb(); atomic_dec((atomic_t *) &(rw)->lock); - wmb(); } void _write_lock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS unsigned long stuck = INIT_STUCK; int cpu = smp_processor_id(); -#endif /* DEBUG_LOCKS */ again: - wmb(); if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */ { while ( (rw)->lock & (1<<31) ) /* wait for write lock */ { -#ifdef DEBUG_LOCKS if(!--stuck) { printk("write_lock(%p) CPU#%d lock %lx)\n", rw, cpu,rw->lock); stuck = INIT_STUCK; } -#endif /* DEBUG_LOCKS */ barrier(); } goto again; @@ -155,14 +162,12 @@ clear_bit(31,&(rw)->lock); while ( (rw)->lock & ~(1<<31) ) { -#ifdef DEBUG_LOCKS if(!--stuck) { printk("write_lock(%p) 2 CPU#%d lock %lx)\n", rw, cpu,rw->lock); stuck = INIT_STUCK; } -#endif /* DEBUG_LOCKS */ barrier(); } goto again; @@ -172,79 +177,12 @@ void _write_unlock(rwlock_t *rw) { -#ifdef DEBUG_LOCKS if ( !(rw->lock & (1<<31)) ) printk("_write_lock(): %s/%d (nip %08lX) lock %lx\n", current->comm,current->pid,current->thread.regs->nip, rw->lock); -#endif /* DEBUG_LOCKS */ wmb(); clear_bit(31,&(rw)->lock); - wmb(); -} - -void __lock_kernel(struct task_struct *task) -{ -#ifdef DEBUG_LOCKS - unsigned long stuck = INIT_STUCK; - - if ( (signed long)(task->lock_depth) < 0 ) - { - printk("__lock_kernel(): %s/%d (nip %08lX) lock depth %x\n", - task->comm,task->pid,task->thread.regs->nip, - task->lock_depth); - } -#endif /* DEBUG_LOCKS */ - - if (atomic_inc_return((atomic_t *) &task->lock_depth) != 1) - return; - /* mine! */ - while (__spin_trylock(&klock_info.kernel_flag)) { -#ifdef DEBUG_LOCKS - if(!--stuck) { - printk("_lock_kernel() CPU#%d NIP %p\n", - smp_processor_id(), - __builtin_return_address(0)); - stuck = INIT_STUCK; - } -#endif /* DEBUG_LOCKS */ - } - - klock_info.akp = smp_processor_id(); - /* my kernel mode! mine!!! */ } -void __unlock_kernel(struct task_struct *task) -{ -#ifdef DEBUG_LOCKS - if ((task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD)) - { - printk("__unlock_kernel(): %s/%d (nip %08lX) " - "lock depth %x flags %lx\n", - task->comm,task->pid,task->thread.regs->nip, - task->lock_depth, klock_info.kernel_flag); - klock_info.akp = NO_PROC_ID; - klock_info.kernel_flag = 0; - return; - } -#endif /* DEBUG_LOCKS */ - if (atomic_dec_and_test((atomic_t *) &task->lock_depth)) - { - wmb(); - klock_info.akp = NO_PROC_ID; - wmb(); - klock_info.kernel_flag = KLOCK_CLEAR; - wmb(); - } -} - -void reacquire_kernel_lock(struct task_struct *task, int cpu,int depth) -{ - if (depth) - { - __cli(); - __lock_kernel(task); - task->lock_depth = depth; - __sti(); - } -} +#endif diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/4xx_mmu.c linux/arch/ppc/mm/4xx_mmu.c --- v2.4.9/linux/arch/ppc/mm/4xx_mmu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/4xx_mmu.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,98 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for initializing the MMU + * on the 4xx series of chips. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Used by the 4xx TLB replacement exception handler. + * Just needed it declared someplace (and initialized to zero). + */ +unsigned int tlb_4xx_index; + +/* + * MMU_init_hw does the chip-specific initialization of the MMU hardware. + */ +void __init MMU_init_hw(void) +{ + /* + * The Zone Protection Register (ZPR) defines how protection will + * be applied to every page which is a member of a given zone. At + * present, we utilize only two of the 4xx's zones. + * The zone index bits (of ZSEL) in the PTE are used for software + * indicators, except the LSB. For user access, zone 15 is used, + * for kernel access, zone 14 is used. We set all but zone 15 + * to zero, allowing only kernel access as indicated in the PTE. + * For zone 15, we set a 01 binary (a value of 10 will not work) + * to allow user access as indicated in the PTE. This also allows + * kernel access as indicated in the PTE. + */ + + mtspr(SPRN_ZPR, 0x00000001); + + flush_instruction_cache(); + + /* + * Set up the real-mode cache parameters for the exception vector + * handlers (which are run in real-mode). + */ + + mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */ + + /* + * Cache instruction and data space where the exception + * vectors and the kernel live in real-mode. + */ + + mtspr(SPRN_DCCR, 0x80000000); /* 128 MB of data space at 0x0. */ + mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */ +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile --- v2.4.9/linux/arch/ppc/mm/Makefile Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/mm/Makefile Tue Aug 28 06:58:33 2001 @@ -1,4 +1,4 @@ -# BK Id: SCCS/s.Makefile 1.6 06/28/01 15:50:17 paulus +# BK Id: SCCS/s.Makefile 1.8 08/16/01 17:25:47 paulus # # # Makefile for the linux ppc-specific parts of the memory manager. @@ -15,15 +15,13 @@ EXTRA_AFLAGS := -Wa,-mppc64bridge endif -O_TARGET := mm.o -obj-y := fault.o init.o mem_pieces.o extable.o +O_TARGET := mm.o +obj-y := fault.o init.o mem_pieces.o extable.o \ + mmu_context.o pgtable.o -ifneq ($(CONFIG_8xx),y) -ifneq ($(CONFIG_4xx),y) -obj-y += hashtable.o -endif -endif - -obj-$(CONFIG_4xx) += 4xx_tlb.o +obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o +obj-$(CONFIG_PPC_ISERIES) += iSeries_hashtable.o iSeries_mmu.o tlb.o +obj-$(CONFIG_4xx) += cachemap.o 4xx_mmu.o +obj-$(CONFIG_8xx) += cachemap.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/cachemap.c linux/arch/ppc/mm/cachemap.c --- v2.4.9/linux/arch/ppc/mm/cachemap.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/cachemap.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,163 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + * + * PowerPC version derived from arch/arm/mm/consistent.c + * Copyright (C) 2001 Dan Malek (dmalek@jlc.net) + * + * linux/arch/arm/mm/consistent.c + * + * Copyright (C) 2000 Russell King + * + * Consistent memory allocators. Used for DMA devices that want to + * share uncached memory with the processor core. The function return + * is the virtual address and 'dma_handle' is the physical address. + * Mostly stolen from the ARM port, with some changes for PowerPC. + * -- Dan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#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 + +void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) +{ + int order, rsize; + unsigned long page; + void *ret; + pte_t *pte; + + if (in_interrupt()) + BUG(); + + /* Only allocate page size areas. + */ + size = PAGE_ALIGN(size); + order = get_order(size); + + page = __get_free_pages(gfp, order); + if (!page) { + BUG(); + return NULL; + } + + /* + * we need to ensure that there are no cachelines in use, + * or worse dirty in this area. + */ + invalidate_dcache_range(page, page + size); + + ret = (void *)page; + *dma_handle = virt_to_bus(ret); + + /* Chase down all of the PTEs and mark them uncached. + */ + rsize = (int)size; + while (rsize > 0) { + if (get_pteptr(&init_mm, page, &pte)) { + pte_val(*pte) |= _PAGE_NO_CACHE | _PAGE_GUARDED; + flush_tlb_page(find_vma(&init_mm,page),page); + } + else { + BUG(); + return NULL; + } + page += PAGE_SIZE; + rsize -= PAGE_SIZE; + } + + return ret; +} + +/* + * free page(s) as defined by the above mapping. + * The caller has to tell us the size so we can free the proper number + * of pages. We can't vmalloc() a new space for these pages and simply + * call vfree() like some other architectures because we could end up + * with aliased cache lines (or at least a cache line with the wrong + * attributes). This can happen when the PowerPC speculative loads + * across page boundaries. + */ +void consistent_free(void *vaddr, size_t size) +{ + int order, rsize; + unsigned long addr; + pte_t *pte; + + if (in_interrupt()) + BUG(); + + size = PAGE_ALIGN(size); + order = get_order(size); + + /* Chase down all of the PTEs and mark them cached again. + */ + addr = (unsigned long)vaddr; + rsize = (int)size; + while (rsize > 0) { + if (get_pteptr(&init_mm, addr, &pte)) { + pte_val(*pte) &= ~(_PAGE_NO_CACHE | _PAGE_GUARDED); + flush_tlb_page(find_vma(&init_mm,addr),addr); + } + else { + BUG(); + return; + } + addr += PAGE_SIZE; + rsize -= PAGE_SIZE; + } + free_pages((unsigned long)vaddr, order); +} + +/* + * make an area consistent. + */ +void consistent_sync(void *vaddr, size_t size, int direction) +{ + unsigned long start = (unsigned long)vaddr; + unsigned long end = start + size; + + switch (direction) { + case PCI_DMA_NONE: + BUG(); + case PCI_DMA_FROMDEVICE: /* invalidate only */ + invalidate_dcache_range(start, end); + break; + case PCI_DMA_TODEVICE: /* writeback only */ + clean_dcache_range(start, end); + break; + case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */ + flush_dcache_range(start, end); + break; + } +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/hashtable.S linux/arch/ppc/mm/hashtable.S --- v2.4.9/linux/arch/ppc/mm/hashtable.S Tue Jul 3 17:08:18 2001 +++ linux/arch/ppc/mm/hashtable.S Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.hashtable.S 1.16 06/29/01 08:51:52 paulus + * BK Id: SCCS/s.hashtable.S 1.18 08/15/01 22:43:07 paulus */ /* * arch/ppc/kernel/hashtable.S @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_SMP .comm hash_table_lock,4 diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.4.9/linux/arch/ppc/mm/init.c Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/mm/init.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.init.c 1.30 07/06/01 09:19:29 trini + * BK Id: SCCS/s.init.c 1.34 08/20/01 22:12:43 paulus */ /* * PowerPC version @@ -21,20 +21,14 @@ */ #include -#include #include #include #include #include #include -#include -#include #include -#include #include -#include #include -#include #include #include #ifdef CONFIG_BLK_DEV_INITRD @@ -47,138 +41,49 @@ #include #include #include -#include -#ifdef CONFIG_8xx -#include -#include -#endif -#ifdef CONFIG_8260 -#include -#include -#endif #include -#include #include -#include -#include -#include +#include #include "mem_pieces.h" +#include "mmu_decl.h" -#if defined(CONFIG_4xx) -#include "4xx_tlb.h" -#endif - -#define MAX_LOW_MEM (512 << 20) +#define MAX_LOW_MEM (0xF0000000UL - KERNELBASE) -#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10) - -mm_context_t next_mmu_context; -unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))]; -#ifdef FEW_CONTEXTS -atomic_t nr_free_contexts; -struct mm_struct *context_mm[LAST_CONTEXT+1]; -void steal_context(void); -#endif /* FEW_CONTEXTS */ - -int prom_trashed; -unsigned long *end_of_DRAM; +void *end_of_DRAM; unsigned long total_memory; unsigned long total_lowmem; -unsigned long ram_phys_base; + int mem_init_done; int init_bootmem_done; int boot_mapsize; unsigned long totalram_pages; unsigned long totalhigh_pages; -extern pgd_t swapper_pg_dir[]; -extern char _start[], _end[]; + +extern char _end[]; extern char etext[], _stext[]; extern char __init_begin, __init_end; extern char __prep_begin, __prep_end; extern char __chrp_begin, __chrp_end; extern char __pmac_begin, __pmac_end; extern char __openfirmware_begin, __openfirmware_end; -unsigned long ioremap_base; -unsigned long ioremap_bot; -unsigned long avail_start; -extern int num_memory; -extern struct mem_info memory[]; -extern boot_infos_t *boot_infos; -extern unsigned int rtas_data, rtas_size; -#ifndef CONFIG_SMP -struct pgtable_cache_struct quicklists; -#endif + #ifdef CONFIG_HIGHMEM pte_t *kmap_pte; pgprot_t kmap_prot; #endif void MMU_init(void); -void *early_get_page(void); -static void mapin_ram(void); -int map_page(unsigned long va, unsigned long pa, int flags); void set_phys_avail(unsigned long total_ram); -extern void die_if_kernel(char *,struct pt_regs *,long); -extern char _start[], _end[]; -extern char _stext[], etext[]; +/* XXX should be in current.h -- paulus */ extern struct task_struct *current_set[NR_CPUS]; char *klimit = _end; struct mem_pieces phys_avail; -PTE *Hash, *Hash_end; -unsigned long Hash_size, Hash_mask; -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -unsigned long _SDR1; -static void hash_init(void); - -union ubat { /* BAT register values to be loaded */ - BAT bat; -#ifdef CONFIG_PPC64BRIDGE - u64 word[2]; -#else - u32 word[2]; -#endif -} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ - -struct batrange { /* stores address ranges mapped by BATs */ - unsigned long start; - unsigned long limit; - unsigned long phys; -} bat_addrs[4]; - -/* - * Return PA for this VA if it is mapped by a BAT, or 0 - */ -static inline unsigned long v_mapped_by_bats(unsigned long va) -{ - int b; - for (b = 0; b < 4; ++b) - if (va >= bat_addrs[b].start && va < bat_addrs[b].limit) - return bat_addrs[b].phys + (va - bat_addrs[b].start); - return 0; -} - -/* - * Return VA for a given PA or 0 if not mapped - */ -static inline unsigned long p_mapped_by_bats(unsigned long pa) -{ - int b; - for (b = 0; b < 4; ++b) - if (pa >= bat_addrs[b].phys - && pa < (bat_addrs[b].limit-bat_addrs[b].start) - +bat_addrs[b].phys) - return bat_addrs[b].start+(pa-bat_addrs[b].phys); - return 0; -} - -#else /* CONFIG_4xx || CONFIG_8xx */ -#define v_mapped_by_bats(x) (0UL) -#define p_mapped_by_bats(x) (0UL) -#endif /* !CONFIG_4xx && !CONFIG_8xx */ +extern char *sysmap; +extern unsigned long sysmap_size; /* * this tells the system to map all of ram with the segregs @@ -298,421 +203,7 @@ val->mem_unit = PAGE_SIZE; } -void * -ioremap(unsigned long addr, unsigned long size) -{ - return __ioremap(addr, size, _PAGE_NO_CACHE); -} - -void * -__ioremap(unsigned long addr, unsigned long size, unsigned long flags) -{ - unsigned long p, v, i; - int err; - - /* - * Choose an address to map it to. - * Once the vmalloc system is running, we use it. - * Before then, we map addresses >= ioremap_base - * virt == phys; for addresses below this we use - * space going down from ioremap_base (ioremap_bot - * records where we're up to). - */ - p = addr & PAGE_MASK; - size = PAGE_ALIGN(addr + size) - p; - - /* - * If the address lies within the first 16 MB, assume it's in ISA - * memory space - */ - if ( p < 16*1024*1024 ) - p += _ISA_MEM_BASE; - - /* - * Don't allow anybody to remap normal RAM that we're using. - * mem_init() sets high_memory so only do the check after that. - */ - if ( mem_init_done && (p < virt_to_phys(high_memory)) ) - { - printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p, - __builtin_return_address(0)); - return NULL; - } - - if (size == 0) - return NULL; - - /* - * Is it already mapped? Perhaps overlapped by a previous - * BAT mapping. If the whole area is mapped then we're done, - * otherwise remap it since we want to keep the virt addrs for - * each request contiguous. - * - * We make the assumption here that if the bottom and top - * of the range we want are mapped then it's mapped to the - * same virt address (and this is contiguous). - * -- Cort - */ - if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ ) - goto out; - - if (mem_init_done) { - struct vm_struct *area; - area = get_vm_area(size, VM_IOREMAP); - if (area == 0) - return NULL; - v = VMALLOC_VMADDR(area->addr); - } else { -#ifndef CONFIG_HIGHMEM - if (p >= ioremap_base) -#else - if (p >= ioremap_base && p < PKMAP_BASE) -#endif /* CONFIG_HIGHMEM */ - v = p; - else - v = (ioremap_bot -= size); - } - - if ((flags & _PAGE_PRESENT) == 0) - flags |= pgprot_val(PAGE_KERNEL); - if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) - flags |= _PAGE_GUARDED; - - /* - * Should check if it is a candidate for a BAT mapping - */ - - err = 0; - for (i = 0; i < size && err == 0; i += PAGE_SIZE) - err = map_page(v+i, p+i, flags); - if (err) { - if (mem_init_done) - vfree((void *)v); - return NULL; - } - -out: - return (void *) (v + (addr & ~PAGE_MASK)); -} - -void iounmap(void *addr) -{ - if (addr > high_memory && (unsigned long) addr < ioremap_bot) - vfree((void *) (PAGE_MASK & (unsigned long) addr)); -} - -unsigned long iopa(unsigned long addr) -{ - unsigned long pa; - pmd_t *pd; - pte_t *pg; - - /* Check the BATs */ - pa = v_mapped_by_bats(addr); - if (pa) - return pa; - - /* Do we have a page table? */ - if (init_mm.pgd == NULL) - return 0; - - /* Use upper 10 bits of addr to index the first level map */ - pd = (pmd_t *) (init_mm.pgd + (addr >> PGDIR_SHIFT)); - if (pmd_none(*pd)) - return 0; - - /* Use middle 10 bits of addr to index the second-level map */ - pg = pte_offset(pd, addr); - return (pte_val(*pg) & PAGE_MASK) | (addr & ~PAGE_MASK); -} - -int -map_page(unsigned long va, unsigned long pa, int flags) -{ - pmd_t *pd; - pte_t *pg; - int err = -ENOMEM; - - spin_lock(&init_mm.page_table_lock); - /* Use upper 10 bits of VA to index the first level map */ - pd = pmd_offset(pgd_offset_k(va), va); - /* Use middle 10 bits of VA to index the second-level map */ - pg = pte_alloc(&init_mm, pd, va); - if (pg != 0) { - err = 0; - set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) - if (mem_init_done && Hash != 0) - flush_hash_page(0, va, pg); -#endif /* !4xx && !8xx */ - } - spin_unlock(&init_mm.page_table_lock); - return err; -} - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* - * TLB flushing: - * - * - flush_tlb_all() flushes all processes TLBs - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(mm, start, end) flushes a range of pages - * - * since the hardware hash table functions as an extension of the - * tlb as far as the linux tables are concerned, flush it too. - * -- Cort - */ - -/* - * Flush all tlb/hash table entries (except perhaps for those - * mapping RAM starting at PAGE_OFFSET, since they never change). - */ -void -local_flush_tlb_all(void) -{ - /* aargh!!! */ - /* just flush the kernel part of the address space, that's - all that the current callers of this require. -- paulus. */ - local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL); - -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif /* CONFIG_SMP */ -} - -/* - * Flush all the (user) entries for the address space described - * by mm. We can't rely on mm->mmap describing all the entries - * that might be in the hash table. - */ -void -local_flush_tlb_mm(struct mm_struct *mm) -{ - if (Hash == 0) { - _tlbia(); - return; - } - - if (mm->map_count) { - struct vm_area_struct *mp; - for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) - local_flush_tlb_range(mm, mp->vm_start, mp->vm_end); - } else - local_flush_tlb_range(mm, 0, TASK_SIZE); - -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif -} - -void -local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - struct mm_struct *mm; - pmd_t *pmd; - pte_t *pte; - - if (Hash == 0) { - _tlbie(vmaddr); - return; - } - mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); - if (!pmd_none(*pmd)) { - pte = pte_offset(pmd, vmaddr); - if (pte_val(*pte) & _PAGE_HASHPTE) - flush_hash_page(mm->context, vmaddr, pte); - } -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif -} - - -/* - * For each address in the range, find the pte for the address - * and check _PAGE_HASHPTE bit; if it is set, find and destroy - * the corresponding HPTE. - */ -void -local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) -{ - pmd_t *pmd; - pte_t *pte; - unsigned long pmd_end; - unsigned int ctx = mm->context; - - if (Hash == 0) { - _tlbia(); - return; - } - start &= PAGE_MASK; - if (start >= end) - return; - pmd = pmd_offset(pgd_offset(mm, start), start); - do { - pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK; - if (!pmd_none(*pmd)) { - if (!pmd_end || pmd_end > end) - pmd_end = end; - pte = pte_offset(pmd, start); - do { - if ((pte_val(*pte) & _PAGE_HASHPTE) != 0) - flush_hash_page(ctx, start, pte); - start += PAGE_SIZE; - ++pte; - } while (start && start < pmd_end); - } else { - start = pmd_end; - } - ++pmd; - } while (start && start < end); - -#ifdef CONFIG_SMP - smp_send_tlb_invalidate(0); -#endif -} - -/* - * Set up one of the I/D BAT (block address translation) register pairs. - * The parameters are not checked; in particular size must be a power - * of 2 between 128k and 256M. - */ -void __init setbat(int index, unsigned long virt, unsigned long phys, - unsigned int size, int flags) -{ - unsigned int bl; - int wimgxpp; - union ubat *bat = BATS[index]; - - bl = (size >> 17) - 1; - if ((_get_PVR() >> 16) != 1) { - /* 603, 604, etc. */ - /* Do DBAT first */ - wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE - | _PAGE_COHERENT | _PAGE_GUARDED); - wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX; - bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ - bat[1].word[1] = phys | wimgxpp; -#ifndef CONFIG_KGDB /* want user access for breakpoints */ - if (flags & _PAGE_USER) -#endif - bat[1].bat.batu.vp = 1; - if (flags & _PAGE_GUARDED) { - /* G bit must be zero in IBATs */ - bat[0].word[0] = bat[0].word[1] = 0; - } else { - /* make IBAT same as DBAT */ - bat[0] = bat[1]; - } - } else { - /* 601 cpu */ - if (bl > BL_8M) - bl = BL_8M; - wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE - | _PAGE_COHERENT); - wimgxpp |= (flags & _PAGE_RW)? - ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX; - bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */ - bat->word[1] = phys | bl | 0x40; /* V=1 */ - } - - bat_addrs[index].start = virt; - bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1; - bat_addrs[index].phys = phys; -} - -#define IO_PAGE (_PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_RW) -#ifdef CONFIG_SMP -#define RAM_PAGE (_PAGE_RW|_PAGE_COHERENT) -#else -#define RAM_PAGE (_PAGE_RW) -#endif -#endif /* CONFIG_8xx */ - -/* - * Map in all of physical memory starting at KERNELBASE. - */ -static void __init mapin_ram(void) -{ - unsigned long v, p, s, f; - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_POWER4) - if (!__map_without_bats) { - unsigned long tot, bl, done; - unsigned long max_size = (256<<20); - unsigned long align; - - /* Set up BAT2 and if necessary BAT3 to cover RAM. */ - - /* Make sure we don't map a block larger than the - smallest alignment of the physical address. */ - /* alignment of ram_phys_base */ - align = ~(ram_phys_base-1) & ram_phys_base; - /* set BAT block size to MIN(max_size, align) */ - if (align && align < max_size) - max_size = align; - - tot = total_lowmem; - for (bl = 128<<10; bl < max_size; bl <<= 1) { - if (bl * 2 > tot) - break; - } - - setbat(2, KERNELBASE, ram_phys_base, bl, RAM_PAGE); - done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1; - if ((done < tot) && !bat_addrs[3].limit) { - /* use BAT3 to cover a bit more */ - tot -= done; - for (bl = 128<<10; bl < max_size; bl <<= 1) - if (bl * 2 > tot) - break; - setbat(3, KERNELBASE+done, ram_phys_base+done, bl, - RAM_PAGE); - } - } -#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_POWER4 */ - - v = KERNELBASE; - p = ram_phys_base; - for (s = 0; s < total_lowmem; s += PAGE_SIZE) { - /* On the MPC8xx, we want the page shared so we - * don't get ASID compares on kernel space. - */ - f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED; -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) - /* Allows stub to set breakpoints everywhere */ - f |= _PAGE_RW | _PAGE_DIRTY; -#else - if ((char *) v < _stext || (char *) v >= etext) - f |= _PAGE_RW | _PAGE_DIRTY; -#ifndef CONFIG_8xx - else - /* On the powerpc (not 8xx), no user access - forces R/W kernel access */ - f |= _PAGE_USER; -#endif /* CONFIG_8xx */ -#endif /* CONFIG_KGDB */ - map_page(v, p, f); - v += PAGE_SIZE; - p += PAGE_SIZE; - } -} - -/* This is only called until mem_init is done. */ -void __init *early_get_page(void) -{ - void *p; - - if (init_bootmem_done) { - p = alloc_bootmem_pages(PAGE_SIZE); - } else { - p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE); - } - return p; -} - +/* Free up now-unused memory */ static void free_sec(unsigned long start, unsigned long end, const char *name) { unsigned long cnt = 0; @@ -725,7 +216,7 @@ start += PAGE_SIZE; } if (cnt) { - printk(" %ldk %s", PGTOKB(cnt), name); + printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name); totalram_pages += cnt; } } @@ -766,110 +257,54 @@ #endif /* - * Initialize the context management stuff. + * Check for command-line options that affect what MMU_init will do. */ -static void mmu_context_init(void) +void MMU_setup(void) { - context_map[0] = 1; /* init_mm uses context 0 */ - next_mmu_context = 1; -#ifdef FEW_CONTEXTS - atomic_set(&nr_free_contexts, LAST_CONTEXT); - context_mm[0] = &init_mm; -#endif /* FEW_CONTEXTS */ -} - -#ifdef FEW_CONTEXTS -/* - * Steal a context from a task that has one at the moment. - * This is only used on 8xx and 4xx and we presently assume that - * they don't do SMP. If they do then this will have to check - * whether the MM we steal is in use. - * We also assume that this is only used on systems that don't - * use an MMU hash table - this is true for 8xx and 4xx. - * This isn't an LRU system, it just frees up each context in - * turn (sort-of pseudo-random replacement :). This would be the - * place to implement an LRU scheme if anyone was motivated to do it. - * -- paulus - */ -void steal_context(void) -{ - struct mm_struct *mm; - - /* free up context `next_mmu_context' */ - /* if we shouldn't free context 0, don't... */ -#ifdef CONFIG_4xx - if (next_mmu_context == 0) - next_mmu_context = 1; -#endif /* CONFIG_4xx */ - mm = context_mm[next_mmu_context]; - flush_tlb_mm(mm); - destroy_context(mm); + /* Check for nobats option (used in mapin_ram). */ + if (strstr(cmd_line, "nobats")) { + __map_without_bats = 1; + } + + /* Look for mem= option on command line */ + if (strstr(cmd_line, "mem=")) { + char *p, *q; + unsigned long maxmem = 0; + + 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; + } } -#endif /* FEW_CONTEXTS */ - -extern boot_infos_t *disp_bi; /* - * Do very early mm setup such as finding the size of memory - * and setting up the hash table. - * A lot of this is prep/pmac specific but a lot of it could - * still be merged. - * -- Cort + * MMU_init sets up the basic memory mappings for the kernel, + * including both RAM and possibly some I/O regions, + * and sets up the page tables and the MMU hardware ready to go. */ -#if defined(CONFIG_4xx) -void __init -MMU_init(void) +void __init MMU_init(void) { - /* - * The Zone Protection Register (ZPR) defines how protection will - * be applied to every page which is a member of a given zone. At - * present, we utilize only two of the 4xx's zones. - * The zone index bits (of ZSEL) in the PTE are used for software - * indicators, except the LSB. For user access, zone 15 is used, - * for kernel access, zone 14 is used. We set all but zone 15 - * to zero, allowing only kernel access as indicated in the PTE. - * For zone 15, we set a 10 binary (I guess a 01 would work too) - * to allow user access as indicated in the PTE. This also allows - * kernel access as indicated in the PTE. - */ + if (ppc_md.progress) + ppc_md.progress("MMU:enter", 0x111); - mtspr(SPRN_ZPR, 0x00000002); - - flush_instruction_cache(); + /* parse args from command line */ + MMU_setup(); /* - * Find the top of physical memory and map all of it in starting - * at KERNELBASE. + * Figure out how much memory we have, how much + * is lowmem, and how much is highmem. */ - - total_memory = total_lowmem = ppc_md.find_end_of_memory(); - end_of_DRAM = __va(total_lowmem); - set_phys_avail(total_lowmem); - mapin_ram(); - - /* - * Set up the real-mode cache parameters for the exception vector - * handlers (which are run in real-mode). - */ - - mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */ - - /* - * Cache instruction and data space where the exception - * vectors and the kernel live in real-mode. - */ - - mtspr(SPRN_DCCR, 0x80000000); /* 128 MB of data space at 0x0. */ - mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */ - - mmu_context_init(); -} - -#else /* !CONFIG_4xx */ -void __init MMU_init(void) -{ - if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111); - total_memory = ppc_md.find_end_of_memory(); if (__max_memory && total_memory > __max_memory) @@ -884,114 +319,54 @@ end_of_DRAM = __va(total_lowmem); set_phys_avail(total_lowmem); -#if !defined(CONFIG_8xx) - if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300); - hash_init(); -#ifndef CONFIG_PPC64BRIDGE - _SDR1 = __pa(Hash) | (Hash_mask >> 10); -#endif - - ioremap_base = 0xf8000000; -#endif /* CONFIG_8xx */ + /* Initialize the MMU hardware */ + if (ppc_md.progress) + ppc_md.progress("MMU:hw init", 0x300); + MMU_init_hw(); - if ( ppc_md.progress ) ppc_md.progress("MMU:mapin", 0x301); /* Map in all of RAM starting at KERNELBASE */ + if (ppc_md.progress) + ppc_md.progress("MMU:mapin", 0x301); mapin_ram(); -#if defined(CONFIG_8xx) - /* Now map in some of the I/O space that is generically needed - * or shared with multiple devices. - * All of this fits into the same 4Mbyte region, so it only - * requires one page table page. - */ - ioremap(IMAP_ADDR, IMAP_SIZE); -#ifdef CONFIG_MBX - ioremap(NVRAM_ADDR, NVRAM_SIZE); - ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE); - ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE); - - /* Map some of the PCI/ISA I/O space to get the IDE interface. - */ - ioremap(PCI_ISA_IO_ADDR, 0x4000); - ioremap(PCI_IDE_ADDR, 0x4000); -#endif -#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) - ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE); -#if !defined(CONFIG_PCI) - ioremap(_IO_BASE,_IO_BASE_SIZE); -#endif -#endif -#ifdef CONFIG_HTDMSOUND - ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE); -#endif -#ifdef CONFIG_FADS - ioremap(BCSR_ADDR, BCSR_SIZE); -#endif -#ifdef CONFIG_PCI - ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE); -#endif -#else /* !CONFIG_8xx */ - /* - * Setup the bat mappings we're going to load that cover - * the io areas. RAM was mapped by mapin_ram(). - * -- Cort - */ - if ( ppc_md.progress ) ppc_md.progress("MMU:setbat", 0x302); - switch (_machine) { - case _MACH_prep: - setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); - setbat(1, 0xf0000000, 0xc0000000, 0x08000000, IO_PAGE); - ioremap_base = 0xf0000000; - break; - case _MACH_chrp: - /* - * The code below tends to get removed, please don't take it out. - * The F50 needs this mapping and it you take it out I'll track you - * down and slap your hands. If it causes problems please email me. - * -- Cort - */ -#ifndef CONFIG_POWER3 - setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); - setbat(1, 0x90000000, 0x90000000, 0x10000000, IO_PAGE); -#endif - break; - case _MACH_Pmac: - ioremap_base = 0xfe000000; - break; - case _MACH_apus: - /* Map PPC exception vectors. */ - setbat(0, 0xfff00000, 0xfff00000, 0x00020000, RAM_PAGE); - /* Map chip and ZorroII memory */ - setbat(1, zTwoBase, 0x00000000, 0x01000000, IO_PAGE); - break; - case _MACH_gemini: - setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE); - setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); - break; - case _MACH_8260: - /* Map the IMMR, plus anything else we can cover - * in that upper space according to the memory controller - * chip select mapping. Grab another bunch of space - * below that for stuff we can't cover in the upper. - */ - setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE); - setbat(1, 0xe0000000, 0xe0000000, 0x10000000, IO_PAGE); - ioremap_base = 0xe0000000; - break; - } +#ifdef CONFIG_HIGHMEM + ioremap_base = PKMAP_BASE; +#else + ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */ +#endif /* CONFIG_HIGHMEM */ ioremap_bot = ioremap_base; -#endif /* CONFIG_8xx */ - if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211); + /* Map in I/O resources */ + if (ppc_md.progress) + ppc_md.progress("MMU:setio", 0x302); + if (ppc_md.setup_io_mappings) + ppc_md.setup_io_mappings(); + + /* Initialize the context management stuff */ + mmu_context_init(); + + if (ppc_md.progress) + ppc_md.progress("MMU:exit", 0x211); + #ifdef CONFIG_BOOTX_TEXT /* Must be done last, or ppc_md.progress will die */ - if (_machine == _MACH_Pmac || _machine == _MACH_chrp) - map_bootx_text(); + if (have_of) + map_boot_text(); #endif +} - mmu_context_init(); +/* This is only called until mem_init is done. */ +void __init *early_get_page(void) +{ + void *p; + + if (init_bootmem_done) { + p = alloc_bootmem_pages(PAGE_SIZE); + } else { + p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE); + } + return p; } -#endif /* CONFIG_4xx */ /* * Initialize the bootmem system and give it all the memory we @@ -1068,8 +443,6 @@ void __init mem_init(void) { - extern char *sysmap; - extern unsigned long sysmap_size; unsigned long addr; int codepages = 0; int datapages = 0; @@ -1094,7 +467,7 @@ make sure the ramdisk pages aren't reserved. */ if (initrd_start) { for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE) - clear_bit(PG_reserved, &virt_to_page(addr)->flags); + ClearPageReserved(virt_to_page(addr)); } #endif /* CONFIG_BLK_DEV_INITRD */ @@ -1106,7 +479,7 @@ addr += PAGE_SIZE) SetPageReserved(virt_to_page(addr)); #endif /* defined(CONFIG_ALL_PPC) */ - if ( sysmap_size ) + if ( sysmap ) for (addr = (unsigned long)sysmap; addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ; addr += PAGE_SIZE) @@ -1147,133 +520,12 @@ codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10), initpages<< (PAGE_SHIFT-10), (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); + if (sysmap) + printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n", + (unsigned int)sysmap, sysmap_size); mem_init_done = 1; } -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* - * Initialize the hash table and patch the instructions in hashtable.S. - */ -static void __init hash_init(void) -{ - int Hash_bits, mb, mb2; - unsigned int hmask, h; - - extern unsigned int hash_page_patch_A[]; - extern unsigned int hash_page_patch_B[], hash_page_patch_C[]; - extern unsigned int hash_page[]; - extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[]; - -#ifdef CONFIG_PPC64BRIDGE - /* The hash table has already been allocated and initialized - in prom.c */ - Hash_mask = (Hash_size >> 7) - 1; - hmask = Hash_mask >> 9; - Hash_bits = __ilog2(Hash_size) - 7; - mb = 25 - Hash_bits; - if (Hash_bits > 16) - Hash_bits = 16; - mb2 = 25 - Hash_bits; - -#else /* CONFIG_PPC64BRIDGE */ - - if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); - /* - * Allow 64k of hash table for every 16MB of memory, - * up to a maximum of 2MB. - */ - for (h = 64<<10; h < total_memory / 256 && h < (2<<20); h *= 2) - ; - Hash_size = h; - Hash_mask = (h >> 6) - 1; - hmask = Hash_mask >> 10; - Hash_bits = __ilog2(h) - 6; - mb = 26 - Hash_bits; - if (Hash_bits > 16) - Hash_bits = 16; - mb2 = 26 - Hash_bits; - - /* shrink the htab since we don't use it on 603's -- Cort */ - switch (_get_PVR()>>16) { - case 3: /* 603 */ - case 6: /* 603e */ - case 7: /* 603ev */ - case 0x0081: /* 82xx */ - Hash_size = 0; - Hash_mask = 0; - break; - default: - /* on 601/4 let things be */ - break; - } - - if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); - /* Find some memory for the hash table. */ - if ( Hash_size ) { - Hash = mem_pieces_find(Hash_size, Hash_size); - cacheable_memzero(Hash, Hash_size); - _SDR1 = __pa(Hash) | (Hash_mask >> 10); - } else - Hash = 0; -#endif /* CONFIG_PPC64BRIDGE */ - - printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", - total_memory >> 20, Hash_size >> 10, Hash); - if ( Hash_size ) - { - if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); - Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); - - /* - * Patch up the instructions in hashtable.S:create_hpte - */ - hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) - | ((unsigned int)(Hash) >> 16); - hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) - | (mb << 6); - hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) - | (mb2 << 6); - hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) - | hmask; - hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) - | hmask; - /* - * Ensure that the locations we've patched have been written - * out from the data cache and invalidated in the instruction - * cache, on those machines with split caches. - */ - flush_icache_range((unsigned long) &hash_page_patch_A[0], - (unsigned long) &hash_page_patch_C[1]); - /* - * Patch up the instructions in hashtable.S:flush_hash_page - */ - flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff) - | ((unsigned int)(Hash) >> 16); - flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) - | (mb << 6); - flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) - | (mb2 << 6); - flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) - | hmask; - flush_icache_range((unsigned long) &flush_hash_patch_A[0], - (unsigned long) &flush_hash_patch_B[1]); - } - else { - Hash_end = 0; - /* - * Put a blr (procedure return) instruction at the - * start of hash_page, since we can still get DSI - * exceptions on a 603. - */ - hash_page[0] = 0x4e800020; - flush_icache_range((unsigned long) &hash_page[0], - (unsigned long) &hash_page[1]); - } - - if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); -} -#endif /* !CONFIG_4xx && !CONFIG_8xx */ - /* * Set phys_avail to the amount of physical memory, * less the kernel text/data/bss. @@ -1314,12 +566,16 @@ /* remove the RTAS pages from the available memory */ if (rtas_data) mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); + /* remove the sysmap pages from the available memory */ + if (sysmap) + mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1); #endif /* CONFIG_ALL_PPC */ -#ifdef CONFIG_PPC64BRIDGE - /* Remove the hash table from the available memory */ - if (Hash) - mem_pieces_remove(&phys_avail, __pa(Hash), Hash_size, 1); -#endif /* CONFIG_PPC64BRIDGE */ +} + +/* Mark some memory as reserved by removing it from phys_avail. */ +void __init reserve_phys_mem(unsigned long start, unsigned long size) +{ + mem_pieces_remove(&phys_avail, start, size, 1); } void flush_page_to_ram(struct page *page) @@ -1328,32 +584,6 @@ __flush_page_to_ram(vaddr); kunmap(page); } - -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -/* - * This is called at the end of handling a user page fault, when the - * fault has been handled by updating a PTE in the linux page tables. - * We use it to preload an HPTE into the hash table corresponding to - * the updated linux PTE. - */ -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, - pte_t pte) -{ - struct mm_struct *mm; - pmd_t *pmd; - pte_t *ptep; - static int nopreload; - - if (Hash == 0 || nopreload) - return; - mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; - pmd = pmd_offset(pgd_offset(mm, address), address); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, address); - add_hash_page(mm->context, address, ptep); - } -} -#endif /* !4xx && !8xx */ /* * set_pte stores a linux PTE into the linux page table. diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/mmu_context.c linux/arch/ppc/mm/mmu_context.c --- v2.4.9/linux/arch/ppc/mm/mmu_context.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/mmu_context.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,89 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for handling the MMU on those + * PowerPC implementations where the MMU substantially follows the + * architecture specification. This includes the 6xx, 7xx, 7xxx, + * 8260, and POWER3 implementations but excludes the 8xx and 4xx. + * Although the iSeries hardware does comply with the architecture + * specification, the need to work through the hypervisor makes + * things sufficiently different that it is handled elsewhere. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include + +#include + +mm_context_t next_mmu_context; +unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))]; +#ifdef FEW_CONTEXTS +atomic_t nr_free_contexts; +struct mm_struct *context_mm[LAST_CONTEXT+1]; +void steal_context(void); +#endif /* FEW_CONTEXTS */ + +/* + * Initialize the context management stuff. + */ +void __init mmu_context_init(void) +{ + /* + * Some processors have too few contexts to reserve one for + * init_mm, and require using context 0 for a normal task. + * Other processors reserve the use of context zero for the kernel. + * This code assumes FIRST_CONTEXT < 32. + */ + context_map[0] = (1 << FIRST_CONTEXT) - 1; + next_mmu_context = FIRST_CONTEXT; +#ifdef FEW_CONTEXTS + atomic_set(&nr_free_contexts, LAST_CONTEXT); +#endif /* FEW_CONTEXTS */ +} + +#ifdef FEW_CONTEXTS +/* + * Steal a context from a task that has one at the moment. + * This is only used on 8xx and 4xx and we presently assume that + * they don't do SMP. If they do then this will have to check + * whether the MM we steal is in use. + * We also assume that this is only used on systems that don't + * use an MMU hash table - this is true for 8xx and 4xx. + * This isn't an LRU system, it just frees up each context in + * turn (sort-of pseudo-random replacement :). This would be the + * place to implement an LRU scheme if anyone was motivated to do it. + * -- paulus + */ +void steal_context(void) +{ + struct mm_struct *mm; + + /* free up context `next_mmu_context' */ + /* if we shouldn't free context 0, don't... */ + if (next_mmu_context < FIRST_CONTEXT) + next_mmu_context = FIRST_CONTEXT; + mm = context_mm[next_mmu_context]; + flush_tlb_mm(mm); + destroy_context(mm); +} +#endif /* FEW_CONTEXTS */ diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/mmu_decl.h linux/arch/ppc/mm/mmu_decl.h --- v2.4.9/linux/arch/ppc/mm/mmu_decl.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/mmu_decl.h Tue Aug 28 06:58:33 2001 @@ -0,0 +1,73 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Declarations of procedures and variables shared between files + * in arch/ppc/mm/. + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +extern void mapin_ram(void); +extern void bat_mapin_ram(void); +extern int map_page(unsigned long va, unsigned long pa, int flags); +extern void setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags); +extern void reserve_phys_mem(unsigned long start, unsigned long size); + +extern int __map_without_bats; +extern void *end_of_DRAM; +extern unsigned long ioremap_base; +extern unsigned long ioremap_bot; +extern unsigned int rtas_data, rtas_size; + +extern unsigned long total_memory; +extern unsigned long total_lowmem; +extern unsigned long ram_phys_base; +extern int mem_init_done; + +extern PTE *Hash, *Hash_end; +extern unsigned long Hash_size, Hash_mask; + +/* ...and now those things that may be slightly different between processor + * architectures. -- Dan + */ +#if defined(CONFIG_8xx) +#define flush_HPTE(X, va, pg) _tlbie(va) +#define MMU_init_hw() do { } while(0) + +#elif defined(CONFIG_4xx) +#define flush_HPTE(X, va, pg) _tlbie(va) + +#else +/* anything except 4xx or 8xx */ +extern void MMU_init_hw(void); + +/* Be careful....this needs to be updated if we ever encounter 603 SMPs, + * which includes all new 82xx processors. We need tlbie/tlbsync here + * in that case (I think). -- Dan. + */ +static inline void flush_HPTE(unsigned context, unsigned long va, pte_t *pg) +{ + if ((Hash != 0) && + (cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE)) + flush_hash_page(0, va, pg); + else + _tlbie(va); +} +#endif diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/pgtable.c linux/arch/ppc/mm/pgtable.c --- v2.4.9/linux/arch/ppc/mm/pgtable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/pgtable.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,360 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines setting up the linux page tables. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mmu_decl.h" + +unsigned long ram_phys_base; + +unsigned long ioremap_base; +unsigned long ioremap_bot; +int io_bat_index; + +#ifndef CONFIG_SMP +struct pgtable_cache_struct quicklists; +#endif + +#if defined(CONFIG_6xx) || defined(CONFIG_POWER3) +#define HAVE_BATS 1 +#endif + +extern char etext[], _stext[]; + +#ifdef HAVE_BATS +extern unsigned long v_mapped_by_bats(unsigned long va); +extern unsigned long p_mapped_by_bats(unsigned long pa); +void setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags); + +#else /* !HAVE_BATS */ +#define v_mapped_by_bats(x) (0UL) +#define p_mapped_by_bats(x) (0UL) +#endif /* HAVE_BATS */ + +#ifndef CONFIG_PPC_ISERIES +void * +ioremap(unsigned long addr, unsigned long size) +{ + return __ioremap(addr, size, _PAGE_NO_CACHE); +} + +void * +__ioremap(unsigned long addr, unsigned long size, unsigned long flags) +{ + unsigned long p, v, i; + int err; + + /* + * Choose an address to map it to. + * Once the vmalloc system is running, we use it. + * Before then, we use space going down from ioremap_base + * (ioremap_bot records where we're up to). + */ + p = addr & PAGE_MASK; + size = PAGE_ALIGN(addr + size) - p; + + /* + * If the address lies within the first 16 MB, assume it's in ISA + * memory space + */ + if (p < 16*1024*1024) + p += _ISA_MEM_BASE; + + /* + * Don't allow anybody to remap normal RAM that we're using. + * mem_init() sets high_memory so only do the check after that. + */ + if ( mem_init_done && (p < virt_to_phys(high_memory)) ) + { + printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p, + __builtin_return_address(0)); + return NULL; + } + + if (size == 0) + return NULL; + + /* + * Is it already mapped? Perhaps overlapped by a previous + * BAT mapping. If the whole area is mapped then we're done, + * otherwise remap it since we want to keep the virt addrs for + * each request contiguous. + * + * We make the assumption here that if the bottom and top + * of the range we want are mapped then it's mapped to the + * same virt address (and this is contiguous). + * -- Cort + */ + if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ ) + goto out; + + if (mem_init_done) { + struct vm_struct *area; + area = get_vm_area(size, VM_IOREMAP); + if (area == 0) + return NULL; + v = VMALLOC_VMADDR(area->addr); + } else { + v = (ioremap_bot -= size); + } + + if ((flags & _PAGE_PRESENT) == 0) + flags |= _PAGE_KERNEL; + if (flags & _PAGE_NO_CACHE) + flags |= _PAGE_GUARDED; + + /* + * Should check if it is a candidate for a BAT mapping + */ + + err = 0; + for (i = 0; i < size && err == 0; i += PAGE_SIZE) + err = map_page(v+i, p+i, flags); + if (err) { + if (mem_init_done) + vfree((void *)v); + return NULL; + } + +out: + return (void *) (v + (addr & ~PAGE_MASK)); +} + +void iounmap(void *addr) +{ + /* + * If mapped by BATs then there is nothing to do. + * Calling vfree() generates a benign warning. + */ + if (v_mapped_by_bats((unsigned long)addr)) return; + + if (addr > high_memory && (unsigned long) addr < ioremap_bot) + vfree((void *) (PAGE_MASK & (unsigned long) addr)); +} +#endif /* CONFIG_PPC_ISERIES */ + +int +map_page(unsigned long va, unsigned long pa, int flags) +{ + pmd_t *pd; + pte_t *pg; + int err = -ENOMEM; + + spin_lock(&init_mm.page_table_lock); + /* Use upper 10 bits of VA to index the first level map */ + pd = pmd_offset(pgd_offset_k(va), va); + /* Use middle 10 bits of VA to index the second-level map */ + pg = pte_alloc(&init_mm, pd, va); + if (pg != 0) { + err = 0; + set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); + if (mem_init_done) + flush_HPTE(0, va, pg); + } + spin_unlock(&init_mm.page_table_lock); + return err; +} + +/* + * Map in all of physical memory starting at KERNELBASE. + */ +void __init mapin_ram(void) +{ + unsigned long v, p, s, f; + +#ifdef HAVE_BATS + if (!__map_without_bats) + bat_mapin_ram(); +#endif /* HAVE_BATS */ + + v = KERNELBASE; + p = ram_phys_base; + for (s = 0; s < total_lowmem; s += PAGE_SIZE) { + /* On the MPC8xx, we want the page shared so we + * don't get ASID compares on kernel space. + */ + f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED; +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) + /* Allows stub to set breakpoints everywhere */ + f |= _PAGE_RW | _PAGE_DIRTY; +#else + if ((char *) v < _stext || (char *) v >= etext) + f |= _PAGE_RW | _PAGE_DIRTY; +#ifndef CONFIG_8xx + else + /* On the powerpc (not 8xx), no user access + forces R/W kernel access */ + f |= _PAGE_USER; +#endif /* CONFIG_8xx */ +#endif /* CONFIG_KGDB */ + map_page(v, p, f); + v += PAGE_SIZE; + p += PAGE_SIZE; + } +} + +/* is x a power of 2? */ +#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) + +/* + * Set up a mapping for a block of I/O. + * virt, phys, size must all be page-aligned. + * This should only be called before ioremap is called. + */ +void __init io_block_mapping(unsigned long virt, unsigned long phys, + unsigned int size, int flags) +{ + int i; + + if (virt > KERNELBASE && virt < ioremap_bot) + ioremap_bot = ioremap_base = virt; + +#ifdef HAVE_BATS + /* + * Use a BAT for this if possible... + */ + if (io_bat_index < 2 && is_power_of_2(size) + && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { + setbat(io_bat_index, virt, phys, size, flags); + ++io_bat_index; + return; + } +#endif /* HAVE_BATS */ + + /* No BATs available, put it in the page tables. */ + for (i = 0; i < size; i += PAGE_SIZE) + map_page(virt + i, phys + i, flags); +} + +/* Scan the real Linux page tables and return a PTE pointer for + * a virtual address in a context. + * Returns true (1) if PTE was found, zero otherwise. The pointer to + * the PTE pointer is unmodified if PTE is not found. + */ +int +get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int retval = 0; + + pgd = pgd_offset(mm, addr & PAGE_MASK); + if (pgd) { + pmd = pmd_offset(pgd, addr & PAGE_MASK); + if (pmd_present(*pmd)) { + pte = pte_offset(pmd, addr & PAGE_MASK); + if (pte) { + retval = 1; + *ptep = pte; + } + } + } + return(retval); +} + +/* Find physical address for this virtual address. Normally used by + * I/O functions, but anyone can call it. + */ +unsigned long iopa(unsigned long addr) +{ + unsigned long pa; + + /* I don't know why this won't work on PMacs or CHRP. It + * appears there is some bug, or there is some implicit + * mapping done not properly represented by BATs or in page + * tables.......I am actively working on resolving this, but + * can't hold up other stuff. -- Dan + */ + pte_t *pte; + struct mm_struct *mm; + + /* Check the BATs */ + pa = v_mapped_by_bats(addr); + if (pa) + return pa; + + /* Allow mapping of user addresses (within the thread) + * for DMA if necessary. + */ + if (addr < TASK_SIZE) + mm = current->mm; + else + mm = &init_mm; + + pa = 0; + if (get_pteptr(mm, addr, &pte)) + pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); + + return(pa); +} + +/* This is will find the virtual address for a physical one.... + * Swiped from APUS, could be dangerous :-). + * This is only a placeholder until I really find a way to make this + * work. -- Dan + */ +unsigned long +mm_ptov (unsigned long paddr) +{ + unsigned long ret; +#if 0 + if (paddr < 16*1024*1024) + ret = ZTWO_VADDR(paddr); + else { + int i; + + for (i = 0; i < kmap_chunk_count;){ + unsigned long phys = kmap_chunks[i++]; + unsigned long size = kmap_chunks[i++]; + unsigned long virt = kmap_chunks[i++]; + if (paddr >= phys + && paddr < (phys + size)){ + ret = virt + paddr - phys; + goto exit; + } + } + + ret = (unsigned long) __va(paddr); + } +exit: +#ifdef DEBUGPV + printk ("PTOV(%lx)=%lx\n", paddr, ret); +#endif +#else + ret = (unsigned long)paddr + KERNELBASE; +#endif + return ret; +} + diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/ppc_mmu.c linux/arch/ppc/mm/ppc_mmu.c --- v2.4.9/linux/arch/ppc/mm/ppc_mmu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/ppc_mmu.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,313 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for handling the MMU on those + * PowerPC implementations where the MMU substantially follows the + * architecture specification. This includes the 6xx, 7xx, 7xxx, + * 8260, and POWER3 implementations but excludes the 8xx and 4xx. + * Although the iSeries hardware does comply with the architecture + * specification, the need to work through the hypervisor makes + * things sufficiently different that it is handled elsewhere. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "mmu_decl.h" +#include "mem_pieces.h" + +PTE *Hash, *Hash_end; +unsigned long Hash_size, Hash_mask; +unsigned long _SDR1; + +union ubat { /* BAT register values to be loaded */ + BAT bat; +#ifdef CONFIG_PPC64BRIDGE + u64 word[2]; +#else + u32 word[2]; +#endif +} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ + +struct batrange { /* stores address ranges mapped by BATs */ + unsigned long start; + unsigned long limit; + unsigned long phys; +} bat_addrs[4]; + +/* + * Return PA for this VA if it is mapped by a BAT, or 0 + */ +unsigned long v_mapped_by_bats(unsigned long va) +{ + int b; + for (b = 0; b < 4; ++b) + if (va >= bat_addrs[b].start && va < bat_addrs[b].limit) + return bat_addrs[b].phys + (va - bat_addrs[b].start); + return 0; +} + +/* + * Return VA for a given PA or 0 if not mapped + */ +unsigned long p_mapped_by_bats(unsigned long pa) +{ + int b; + for (b = 0; b < 4; ++b) + if (pa >= bat_addrs[b].phys + && pa < (bat_addrs[b].limit-bat_addrs[b].start) + +bat_addrs[b].phys) + return bat_addrs[b].start+(pa-bat_addrs[b].phys); + return 0; +} + +void __init bat_mapin_ram(void) +{ + unsigned long tot, bl, done; + unsigned long max_size = (256<<20); + unsigned long align; + + /* Set up BAT2 and if necessary BAT3 to cover RAM. */ + + /* Make sure we don't map a block larger than the + smallest alignment of the physical address. */ + /* alignment of ram_phys_base */ + align = ~(ram_phys_base-1) & ram_phys_base; + /* set BAT block size to MIN(max_size, align) */ + if (align && align < max_size) + max_size = align; + + tot = total_lowmem; + for (bl = 128<<10; bl < max_size; bl <<= 1) { + if (bl * 2 > tot) + break; + } + + setbat(2, KERNELBASE, ram_phys_base, bl, _PAGE_KERNEL); + done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1; + if ((done < tot) && !bat_addrs[3].limit) { + /* use BAT3 to cover a bit more */ + tot -= done; + for (bl = 128<<10; bl < max_size; bl <<= 1) + if (bl * 2 > tot) + break; + setbat(3, KERNELBASE+done, ram_phys_base+done, bl, + _PAGE_KERNEL); + } +} + +/* + * Set up one of the I/D BAT (block address translation) register pairs. + * The parameters are not checked; in particular size must be a power + * of 2 between 128k and 256M. + */ +void __init setbat(int index, unsigned long virt, unsigned long phys, + unsigned int size, int flags) +{ + unsigned int bl; + int wimgxpp; + union ubat *bat = BATS[index]; + +#ifdef CONFIG_SMP + if ((flags & _PAGE_NO_CACHE) == 0) + flags |= _PAGE_COHERENT; +#endif + bl = (size >> 17) - 1; + if (PVR_VER(mfspr(PVR)) != 1) { + /* 603, 604, etc. */ + /* Do DBAT first */ + wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE + | _PAGE_COHERENT | _PAGE_GUARDED); + wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX; + bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ + bat[1].word[1] = phys | wimgxpp; +#ifndef CONFIG_KGDB /* want user access for breakpoints */ + if (flags & _PAGE_USER) +#endif + bat[1].bat.batu.vp = 1; + if (flags & _PAGE_GUARDED) { + /* G bit must be zero in IBATs */ + bat[0].word[0] = bat[0].word[1] = 0; + } else { + /* make IBAT same as DBAT */ + bat[0] = bat[1]; + } + } else { + /* 601 cpu */ + if (bl > BL_8M) + bl = BL_8M; + wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE + | _PAGE_COHERENT); + wimgxpp |= (flags & _PAGE_RW)? + ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX; + bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */ + bat->word[1] = phys | bl | 0x40; /* V=1 */ + } + + bat_addrs[index].start = virt; + bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1; + bat_addrs[index].phys = phys; +} + +/* + * Initialize the hash table and patch the instructions in hashtable.S. + */ +void __init MMU_init_hw(void) +{ + int Hash_bits, mb, mb2; + unsigned int hmask; + + extern unsigned int hash_page_patch_A[]; + extern unsigned int hash_page_patch_B[], hash_page_patch_C[]; + extern unsigned int hash_page[]; + extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[]; + +#ifdef CONFIG_PPC64BRIDGE + /* The hash table has already been allocated and initialized + in prom.c */ + Hash_mask = (Hash_size >> 7) - 1; + hmask = Hash_mask >> 9; + Hash_bits = __ilog2(Hash_size) - 7; + mb = 25 - Hash_bits; + if (Hash_bits > 16) + Hash_bits = 16; + mb2 = 25 - Hash_bits; + + /* Remove the hash table from the available memory */ + if (Hash) + reserve_phys_mem(__pa(Hash), Hash_size); + +#else /* CONFIG_PPC64BRIDGE */ + unsigned int h; + + if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE) == 0) + return; + if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); + /* + * Allow 64k of hash table for every 16MB of memory, + * up to a maximum of 2MB. + */ + for (h = 64<<10; h < total_memory / 256 && h < (2<<20); h *= 2) + ; + Hash_size = h; + Hash_mask = (h >> 6) - 1; + hmask = Hash_mask >> 10; + Hash_bits = __ilog2(h) - 6; + mb = 26 - Hash_bits; + if (Hash_bits > 16) + Hash_bits = 16; + mb2 = 26 - Hash_bits; + + if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); + /* Find some memory for the hash table. */ + if ( Hash_size ) { + Hash = mem_pieces_find(Hash_size, Hash_size); + cacheable_memzero(Hash, Hash_size); + _SDR1 = __pa(Hash) | (Hash_mask >> 10); + } else + Hash = 0; +#endif /* CONFIG_PPC64BRIDGE */ + + printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", + total_memory >> 20, Hash_size >> 10, Hash); + if (Hash_size) { + if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); + Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); + + /* + * Patch up the instructions in hashtable.S:create_hpte + */ + hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) + | ((unsigned int)(Hash) >> 16); + hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) + | (mb << 6); + hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) + | (mb2 << 6); + hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) + | hmask; + hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) + | hmask; + /* + * Ensure that the locations we've patched have been written + * out from the data cache and invalidated in the instruction + * cache, on those machines with split caches. + */ + flush_icache_range((unsigned long) &hash_page_patch_A[0], + (unsigned long) &hash_page_patch_C[1]); + /* + * Patch up the instructions in hashtable.S:flush_hash_page + */ + flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff) + | ((unsigned int)(Hash) >> 16); + flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) + | (mb << 6); + flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) + | (mb2 << 6); + flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) + | hmask; + flush_icache_range((unsigned long) &flush_hash_patch_A[0], + (unsigned long) &flush_hash_patch_B[1]); + } + else { + Hash_end = 0; + /* + * Put a blr (procedure return) instruction at the + * start of hash_page, since we can still get DSI + * exceptions on a 603. + */ + hash_page[0] = 0x4e800020; + flush_icache_range((unsigned long) &hash_page[0], + (unsigned long) &hash_page[1]); + } + + if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); +} + +/* + * This is called at the end of handling a user page fault, when the + * fault has been handled by updating a PTE in the linux page tables. + * We use it to preload an HPTE into the hash table corresponding to + * the updated linux PTE. + */ +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte) +{ + struct mm_struct *mm; + pmd_t *pmd; + pte_t *ptep; + static int nopreload; + + if (Hash == 0 || nopreload) + return; + mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; + pmd = pmd_offset(pgd_offset(mm, address), address); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, address); + add_hash_page(mm->context, address, ptep); + } +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/mm/tlb.c linux/arch/ppc/mm/tlb.c --- v2.4.9/linux/arch/ppc/mm/tlb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/tlb.c Tue Aug 28 06:58:33 2001 @@ -0,0 +1,162 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * This file contains the routines for TLB flushing. + * On machines where the MMU uses a hash table to store virtual to + * physical translations, these routines flush entries from the the + * hash table also. + * -- paulus + * + * Derived from arch/ppc/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include + +#include "mmu_decl.h" + +/* + * TLB flushing: + * + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + * + * since the hardware hash table functions as an extension of the + * tlb as far as the linux tables are concerned, flush it too. + * -- Cort + */ + +/* + * Flush all tlb/hash table entries (except perhaps for those + * mapping RAM starting at PAGE_OFFSET, since they never change). + */ +void +local_flush_tlb_all(void) +{ + /* aargh!!! */ + /* + * Just flush the kernel part of the address space, that's + * all that the current callers of this require. + * Eventually I hope to persuade the powers that be that + * we can and should dispense with flush_tlb_all(). + * -- paulus. + */ + local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL); + +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif /* CONFIG_SMP */ +} + +/* + * Flush all the (user) entries for the address space described + * by mm. We can't rely on mm->mmap describing all the entries + * that might be in the hash table. + */ +void +local_flush_tlb_mm(struct mm_struct *mm) +{ + if (Hash == 0) { + _tlbia(); + return; + } + + if (mm->map_count) { + struct vm_area_struct *mp; + for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) + local_flush_tlb_range(mm, mp->vm_start, mp->vm_end); + } else + local_flush_tlb_range(mm, 0, TASK_SIZE); + +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif +} + +void +local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) +{ + struct mm_struct *mm; + pmd_t *pmd; + pte_t *pte; + + if (Hash == 0) { + _tlbie(vmaddr); + return; + } + mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; + pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); + if (!pmd_none(*pmd)) { + pte = pte_offset(pmd, vmaddr); + if (pte_val(*pte) & _PAGE_HASHPTE) + flush_hash_page(mm->context, vmaddr, pte); + } +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif +} + + +/* + * For each address in the range, find the pte for the address + * and check _PAGE_HASHPTE bit; if it is set, find and destroy + * the corresponding HPTE. + */ +void +local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) +{ + pmd_t *pmd; + pte_t *pte; + unsigned long pmd_end; + unsigned int ctx = mm->context; + + if (Hash == 0) { + _tlbia(); + return; + } + start &= PAGE_MASK; + if (start >= end) + return; + pmd = pmd_offset(pgd_offset(mm, start), start); + do { + pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK; + if (!pmd_none(*pmd)) { + if (!pmd_end || pmd_end > end) + pmd_end = end; + pte = pte_offset(pmd, start); + do { + if ((pte_val(*pte) & _PAGE_HASHPTE) != 0) + flush_hash_page(ctx, start, pte); + start += PAGE_SIZE; + ++pte; + } while (start && start < pmd_end); + } else { + start = pmd_end; + } + ++pmd; + } while (start && start < end); + +#ifdef CONFIG_SMP + smp_send_tlb_invalidate(0); +#endif +} diff -u --recursive --new-file v2.4.9/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.4.9/linux/arch/ppc/vmlinux.lds Mon Aug 27 12:41:39 2001 +++ linux/arch/ppc/vmlinux.lds Tue Aug 28 06:58:33 2001 @@ -70,6 +70,10 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___ftr_fixup = .; + __ftr_fixup : { *(__ftr_fixup) } + __stop___ftr_fixup = .; + . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } diff -u --recursive --new-file v2.4.9/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c --- v2.4.9/linux/arch/ppc/xmon/start.c Mon May 21 17:04:47 2001 +++ linux/arch/ppc/xmon/start.c Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.start.c 1.12 05/21/01 21:39:13 paulus + * BK Id: SCCS/s.start.c 1.16 08/20/01 22:17:58 paulus */ /* * Copyright (C) 1996 Paul Mackerras. @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef CONFIG_SMP #include #endif @@ -25,8 +26,6 @@ static volatile unsigned char *sccc, *sccd; unsigned long TXRDY, RXRDY; extern void xmon_printf(const char *fmt, ...); -extern void prom_drawchar(char); -extern void prom_drawstring(const char *str); static int xmon_expect(const char *str, unsigned int timeout); static int console; @@ -56,6 +55,7 @@ void xmon_map_scc(void) { +#ifdef CONFIG_ALL_PPC volatile unsigned char *base; use_screen = 0; @@ -85,14 +85,34 @@ use_screen = 1; #endif } - prom_drawstring("xmon uses "); + if (!use_screen && (np = find_devices("escc")) != NULL) { + /* + * look for the device node for the serial port + * we're using and see if it says it has a modem + */ + char *name = xmon_use_sccb? "ch-b": "ch-a"; + char *slots; + int l; + + np = np->child; + while (np != NULL && strcmp(np->name, name) != 0) + np = np->sibling; + if (np != NULL) { + /* XXX should parse this properly */ + slots = get_property(np, "slot-names", &l); + if (slots != NULL && l >= 10 + && strcmp(slots+4, "Modem") == 0) + via_modem = 1; + } + } + btext_drawstring("xmon uses "); if (use_screen) - prom_drawstring("screen and keyboard\n"); + btext_drawstring("screen and keyboard\n"); else { if (via_modem) - prom_drawstring("modem on "); - prom_drawstring(xmon_use_sccb? "printer": "modem"); - prom_drawstring(" port\n"); + btext_drawstring("modem on "); + btext_drawstring(xmon_use_sccb? "printer": "modem"); + btext_drawstring(" port\n"); } #endif /* CONFIG_BOOTX_TEXT */ @@ -114,15 +134,6 @@ sccc = base + (addr & ~PAGE_MASK); sccd = sccc + 0x10; } - else if ( _machine & _MACH_gemini ) - { - /* should already be mapped by the kernel boot */ - sccc = (volatile unsigned char *) 0xffeffb0d; - sccd = (volatile unsigned char *) 0xffeffb08; - TXRDY = 0x20; - RXRDY = 1; - console = 1; - } else { /* should already be mapped by the kernel boot */ @@ -135,6 +146,14 @@ TXRDY = 0x20; RXRDY = 1; } +#elif defined(CONFIG_GEMINI) + /* should already be mapped by the kernel boot */ + sccc = (volatile unsigned char *) 0xffeffb0d; + sccd = (volatile unsigned char *) 0xffeffb08; + TXRDY = 0x20; + RXRDY = 1; + console = 1; +#endif /* platform */ } static int scc_initialized = 0; @@ -175,7 +194,7 @@ if (use_screen) { /* write it on the screen */ for (i = 0; i < nb; ++i) - prom_drawchar(*p++); + btext_drawchar(*p++); goto out; } #endif @@ -216,7 +235,7 @@ static unsigned char xmon_keytab[128] = "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */ - "yt123465=97-80o]" /* 0x10 - 0x1f */ + "yt123465=97-80]o" /* 0x10 - 0x1f */ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ @@ -224,7 +243,7 @@ static unsigned char xmon_shift_keytab[128] = "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */ - "YT!@#$^%+(&=*)}O" /* 0x10 - 0x1f */ + "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */ "U{IP\rLJ\"K:|" /* 0x20 - 0x2f */ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ @@ -243,15 +262,15 @@ do { if (--t < 0) { on = 1 - on; - prom_drawchar(on? 0xdb: 0x20); - prom_drawchar('\b'); + btext_drawchar(on? 0xdb: 0x20); + btext_drawchar('\b'); t = 200000; } do_poll_adb(); } while (xmon_adb_keycode == -1); k = xmon_adb_keycode; if (on) - prom_drawstring(" \b"); + btext_drawstring(" \b"); /* test for shift keys */ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) { @@ -544,7 +563,9 @@ xmon_enter(void) { #ifdef CONFIG_ADB_PMU - pmu_suspend(); + if (_machine == _MACH_Pmac) { + pmu_suspend(); + } #endif } @@ -552,6 +573,8 @@ xmon_leave(void) { #ifdef CONFIG_ADB_PMU - pmu_resume(); + if (_machine == _MACH_Pmac) { + pmu_resume(); + } #endif } diff -u --recursive --new-file v2.4.9/linux/arch/sparc/boot/btfixupprep.c linux/arch/sparc/boot/btfixupprep.c --- v2.4.9/linux/arch/sparc/boot/btfixupprep.c Sun Oct 4 10:22:42 1998 +++ linux/arch/sparc/boot/btfixupprep.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: btfixupprep.c,v 1.5 1998/09/16 12:24:55 jj Exp $ +/* $Id: btfixupprep.c,v 1.6 2001/08/22 15:27:47 davem Exp $ Simple utility to prepare vmlinux image for sparc. Resolves all BTFIXUP uses and settings and creates a special .s object to link to the image. @@ -88,6 +88,16 @@ return array + last - 1; } +void set_mode (char *buffer) +{ + for (mode = 0;; mode++) + if (buffer[mode] < '0' || buffer[mode] > '9') + break; + if (mode != 8 && mode != 16) + fatal(); +} + + int main(int argc,char **argv) { char *p, *q; @@ -106,14 +116,6 @@ goto main0; fatal(); main0: - if (fgets (buffer, 1024, stdin) == NULL || buffer[0] < '0' || buffer[0] > '9') - fatal(); - for (mode = 0;; mode++) - if (buffer[mode] < '0' || buffer[mode] > '9') - break; - if (mode != 8 && mode != 16) - fatal(); - rellen = strlen(relrec); while (fgets (buffer, 1024, stdin) != NULL) if (!strncmp (buffer, relrec, rellen)) @@ -132,6 +134,8 @@ int nbase; if (!strncmp (buffer, relrec, rellen)) goto main1; + if (mode == 0) + set_mode (buffer); p = strchr (buffer, '\n'); if (p) *p = 0; if (strlen (buffer) < 22+mode) diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.4.9/linux/arch/sparc64/defconfig Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/defconfig Tue Aug 28 07:09:44 2001 @@ -255,6 +255,7 @@ CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y @@ -264,8 +265,8 @@ # CONFIG_AEC62XX_TUNING is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5530 is not set @@ -276,7 +277,8 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # CONFIG_PDC202XX_BURST is not set -# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/dtlb_backend.S linux/arch/sparc64/kernel/dtlb_backend.S --- v2.4.9/linux/arch/sparc64/kernel/dtlb_backend.S Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/dtlb_backend.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: dtlb_backend.S,v 1.12 2001/08/13 20:41:54 kanoj Exp $ +/* $Id: dtlb_backend.S,v 1.13 2001/08/17 04:55:09 kanoj Exp $ * dtlb_backend.S: Back end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -6,11 +6,27 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff +#include + +#if PAGE_SHIFT == 13 +#define FILL_VALID_SZ_BITS1(r1) \ + sllx %g2, 62, r1 +#define FILL_VALID_SZ_BITS2(r1) +#define FILL_VALID_SZ_BITS_NOP nop +#else /* PAGE_SHIFT */ +#define FILL_VALID_SZ_BITS1(r1) \ + or %g0, 5, r1 +#define FILL_VALID_SZ_BITS2(r1) \ + sllx r1, 61, r1 +#define FILL_VALID_SZ_BITS_NOP +#endif /* PAGE_SHIFT */ + +#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P ) #define VPTE_SHIFT (PAGE_SHIFT - 3) -#define PMD_SHIFT (23 - PAGE_SHIFT + 3) -#define PGD_SHIFT (34 - PAGE_SHIFT + 3) -#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P) +#define TLB_PMD_SHIFT (PAGE_SHIFT - 3 + 3) +#define TLB_PGD_SHIFT (PAGE_SHIFT - 2 + PAGE_SHIFT - 3 + 3) +#define TLB_PMD_MASK (((1 << PMD_BITS) - 1) << 1) +#define TLB_PGD_MASK (((1 << (VA_BITS - PAGE_SHIFT - (PAGE_SHIFT - 3) - PMD_BITS)) - 1) << 2) /* Ways we can get here: * @@ -31,13 +47,13 @@ /* TLB1 ** ICACHE line 2: Quick VPTE miss */ ldxa [%g1] ASI_DMMU, %g5 ! Doing PGD caching? - srlx %g6, (PMD_SHIFT - 1), %g1 ! Position PMD offset + srlx %g6, (TLB_PMD_SHIFT - 1), %g1 ! Position PMD offset be,pn %xcc, sparc64_vpte_nucleus ! Is it from Nucleus? - and %g1, 0xffe, %g1 ! Mask PMD offset bits + and %g1, TLB_PMD_MASK, %g1 ! Mask PMD offset bits brnz,pt %g5, sparc64_vpte_continue ! Yep, go like smoke add %g1, %g1, %g1 ! Position PMD offset some more - srlx %g6, (PGD_SHIFT - 2), %g5 ! Position PGD offset - and %g5, 0xffc, %g5 ! Mask PGD offset + srlx %g6, (TLB_PGD_SHIFT - 2), %g5 ! Position PGD offset + and %g5, TLB_PGD_MASK, %g5 ! Mask PGD offset /* TLB1 ** ICACHE line 3: Quick VPTE miss */ lduwa [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD @@ -48,7 +64,8 @@ lduwa [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD sllx %g5, 11, %g5 ! Shift into place brz,pn %g5, vpte_noent ! Valid? - sllx %g2, 62, %g1 ! Put _PAGE_VALID into %g1 + FILL_VALID_SZ_BITS1(%g1) ! Put _PAGE_VALID into %g1 + FILL_VALID_SZ_BITS2(%g1) ! Put _PAGE_VALID into %g1 or %g5, VPTE_BITS, %g5 ! Prepare VPTE data /* TLB1 ** ICACHE line 4: Quick VPTE miss */ @@ -59,10 +76,15 @@ retry ! Load PTE once again nop nop - nop + FILL_VALID_SZ_BITS_NOP -#undef TAG_CONTEXT_BITS #undef VPTE_SHIFT -#undef PMD_SHIFT -#undef PGD_SHIFT +#undef TLB_PMD_SHIFT +#undef TLB_PGD_SHIFT #undef VPTE_BITS +#undef TLB_PMD_MASK +#undef TLB_PGD_MASK +#undef FILL_VALID_SZ_BITS1 +#undef FILL_VALID_SZ_BITS2 +#undef FILL_VALID_SZ_BITS_NOP + diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/dtlb_base.S linux/arch/sparc64/kernel/dtlb_base.S --- v2.4.9/linux/arch/sparc64/kernel/dtlb_base.S Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/dtlb_base.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: dtlb_base.S,v 1.10 2001/08/13 20:41:54 kanoj Exp $ +/* $Id: dtlb_base.S,v 1.12 2001/08/17 04:55:09 kanoj Exp $ * dtlb_base.S: Front end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -6,11 +6,6 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff -#define VPTE_SHIFT (PAGE_SHIFT - 3) -#define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000) -#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) - /* %g1 TLB_SFSR (%g1 + %g1 == TLB_TAG_ACCESS) * %g2 (KERN_HIGHBITS | KERN_LOWBITS) * %g3 VPTE base (0xfffffffe00000000) Spitfire/Blackbird (44-bit VA space) @@ -48,26 +43,47 @@ * 4) User space accesses by nucleus at tl0 */ +#if PAGE_SHIFT == 13 +/* + * To compute vpte offset, we need to do ((addr >> 13) << 3), + * which can be optimized to (addr >> 10) if bits 10/11/12 can + * be guaranteed to be 0 ... mmu_context.h does guarantee this + * by only using 10 bits in the hwcontext value. + */ +#define CREATE_VPTE_OFFSET1(r1, r2) +#define CREATE_VPTE_OFFSET2(r1, r2) \ + srax r1, 10, r2 +#define CREATE_VPTE_NOP nop +#else +#define CREATE_VPTE_OFFSET1(r1, r2) \ + srax r1, PAGE_SHIFT, r2 +#define CREATE_VPTE_OFFSET2(r1, r2) \ + sllx r2, 3, r2 +#define CREATE_VPTE_NOP +#endif + /* DTLB ** ICACHE line 1: Quick user TLB misses */ ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus? from_tl1_trap: + CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset be,pn %xcc, 3f ! Yep, special processing - srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset + CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE 1: brlz,pt %g5, 9f ! Valid, load into TLB nop ! Delay-slot - ba,a,pt %xcc, 4f ! Invalid, branch out + ba,a,pt %xcc, longpath ! Invalid, branch out /* DTLB ** ICACHE line 2: Quick kernel TLB misses */ 3: brlz,pt %g4, 9f ! Kernel virtual map? xor %g2, %g4, %g5 ! Finish bit twiddles - ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte - ba,pt %xcc, 1b ! Continue tlb reload + ba,pt %xcc, kvmap ! Yep, go check for obp/vmalloc nop + nop 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB retry ! Trap return -4: rdpr %pstate, %g5 ! Move into alternate globals +longpath: + rdpr %pstate, %g5 ! Move into alternate globals /* DTLB ** ICACHE line 3: winfixups+real_faults */ wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate @@ -87,9 +103,8 @@ nop nop nop - nop + CREATE_VPTE_NOP -#undef TAG_CONTEXT_BITS -#undef VPTE_SHIFT -#undef KERN_HIGHBITS -#undef KERN_LOWBITS +#undef CREATE_VPTE_OFFSET1 +#undef CREATE_VPTE_OFFSET2 +#undef CREATE_VPTE_NOP diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.4.9/linux/arch/sparc64/kernel/entry.S Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/entry.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.129 2001/08/13 20:41:54 kanoj Exp $ +/* $Id: entry.S,v 1.134 2001/08/27 18:42:07 kanoj Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -21,7 +21,7 @@ #include #include -/* #define SYSCALL_TRACING */ +/* #define SYSCALL_TRACING 1 */ #define curptr g6 @@ -32,7 +32,25 @@ .globl sparc64_vpte_patchme1 .globl sparc64_vpte_patchme2 +/* + * On a second level vpte miss, check whether the original fault is to the OBP + * range (note that this is only possible for instruction miss, data misses to + * obp range do not use vpte). If so, go back directly to the faulting address. + * This is because we want to read the tpc, otherwise we have no way of knowing + * the 8k aligned faulting address if we are using >8k kernel pagesize. This also + * ensures no vpte range addresses are dropped into tlb while obp is executing + * (see inherit_locked_prom_mappings() rant). + */ sparc64_vpte_nucleus: + mov 0xf, %g5 + sllx %g5, 28, %g5 ! Load 0xf0000000 + cmp %g4, %g5 ! Is addr >= LOW_OBP_ADDRESS? + blu,pn %xcc, sparc64_vpte_patchme1 + mov 0x1, %g5 + sllx %g5, 32, %g5 ! Load 0x100000000 + cmp %g4, %g5 ! Is addr < HI_OBP_ADDRESS? + blu,pn %xcc, obp_iaddr_patch + nop sparc64_vpte_patchme1: sethi %hi(0), %g5 ! This has to be patched sparc64_vpte_patchme2: @@ -45,6 +63,74 @@ stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS done ! Slick trick + .globl obp_iaddr_patch + .globl obp_daddr_patch + +obp_iaddr_patch: + sethi %hi(0), %g5 ! This and following is patched + or %g5, %lo(0), %g5 ! g5 now holds obp pmd base physaddr + wrpr %g0, 1, %tl ! Behave as if we are at TL0 + rdpr %tpc, %g4 ! Find original faulting iaddr + srlx %g4, 13, %g4 ! Throw out context bits + sllx %g4, 13, %g4 ! g4 has vpn + ctx0 now + mov TLB_SFSR, %g1 ! Restore %g1 value + stxa %g4, [%g1 + %g1] ASI_IMMU ! Restore previous TAG_ACCESS + srlx %g4, 23, %g6 ! Find pmd number + and %g6, 0x7ff, %g6 ! Find pmd number + sllx %g6, 2, %g6 ! Find pmd offset + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pmd, ie pagetable physaddr + brz,pn %g5, longpath ! Kill the PROM ? :-) + sllx %g5, 11, %g5 ! Shift into place + srlx %g4, 13, %g6 ! find pte number in pagetable + and %g6, 0x3ff, %g6 ! find pte number in pagetable + sllx %g6, 3, %g6 ! find pte offset in pagetable + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pte + brgez,pn %g5, longpath ! Kill the PROM ? :-) + nop + stxa %g5, [%g0] ASI_ITLB_DATA_IN ! put into tlb + retry ! go back to original fault + +obp_daddr_patch: + sethi %hi(0), %g5 ! This and following is patched + or %g5, %lo(0), %g5 ! g5 now holds obp pmd base physaddr + srlx %g4, 23, %g6 ! Find pmd number + and %g6, 0x7ff, %g6 ! Find pmd number + sllx %g6, 2, %g6 ! Find pmd offset + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pmd, ie pagetable physaddr + brz,pn %g5, longpath + sllx %g5, 11, %g5 ! Shift into place + srlx %g4, 13, %g6 ! find pte number in pagetable + and %g6, 0x3ff, %g6 ! find pte number in pagetable + sllx %g6, 3, %g6 ! find pte offset in pagetable + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5! Load pte + brgez,pn %g5, longpath + nop + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! put into tlb + retry + +/* + * On a first level data miss, check whether this is to the OBP range (note that + * such accesses can be made by prom, as well as by kernel using prom_getproperty + * on "address"), and if so, do not use vpte access ... rather, use information + * saved during inherit_prom_mappings() using 8k pagesize. + */ +kvmap: + mov 0xf, %g5 + sllx %g5, 28, %g5 ! Load 0xf0000000 + cmp %g4, %g5 ! Is addr >= LOW_OBP_ADDRESS? + blu,pn %xcc, vmalloc_addr + mov 0x1, %g5 + sllx %g5, 32, %g5 ! Load 0x100000000 + cmp %g4, %g5 ! Is addr < HI_OBP_ADDRESS? + blu,pn %xcc, obp_daddr_patch + nop +vmalloc_addr: ! vmalloc addr accessed + ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte + brgez,pn %g5, longpath ! Valid, load into TLB + nop + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB + retry + /* This is trivial with the new code... */ .globl do_fpdis do_fpdis: @@ -1413,9 +1499,8 @@ srl %i0, 0, %o0 ! IEU0 sll %g1, 2, %l4 ! IEU0 Group #ifdef SYSCALL_TRACING - add %sp, STACK_BIAS + REGWIN_SZ, %o1 call syscall_trace_entry - mov %g1, %o0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 srl %i0, 0, %o0 #endif mov %i4, %o4 ! IEU1 @@ -1442,9 +1527,8 @@ mov %i0, %o0 ! IEU0 sll %g1, 2, %l4 ! IEU0 Group #ifdef SYSCALL_TRACING - add %sp, STACK_BIAS + REGWIN_SZ, %o1 call syscall_trace_entry - mov %g1, %o0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 mov %i0, %o0 #endif mov %i1, %o1 ! IEU1 @@ -1464,8 +1548,10 @@ 3: stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ret_sys_call: #ifdef SYSCALL_TRACING + mov %o0, %o1 call syscall_trace_exit - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + mov %o1, %o0 #endif ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/iommu_common.c linux/arch/sparc64/kernel/iommu_common.c --- v2.4.9/linux/arch/sparc64/kernel/iommu_common.c Mon Jun 19 17:59:38 2000 +++ linux/arch/sparc64/kernel/iommu_common.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: iommu_common.c,v 1.4 2000/06/04 21:50:23 anton Exp $ +/* $Id: iommu_common.c,v 1.5 2001/08/24 17:57:51 kanoj Exp $ * iommu_common.c: UltraSparc SBUS/PCI common iommu code. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -36,12 +36,12 @@ unsigned long start, end; start = sg[i].dvma_address; - start = start & PAGE_MASK; + start = start & IO_PAGE_MASK; end = sg[i].dvma_address + sg[i].dvma_length; - end = (end + (PAGE_SIZE - 1)) & PAGE_MASK; + end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; - pgcount += ((end - start) >> PAGE_SHIFT); + pgcount += ((end - start) >> IO_PAGE_SHIFT); } if (pgcount != npages) { @@ -70,7 +70,7 @@ unsigned long paddr; /* SG and DMA_SG must begin at the same sub-page boundary. */ - if ((sgaddr & ~PAGE_MASK) != (daddr & ~PAGE_MASK)) { + if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) { printk("verify_one_map: Wrong start offset " "sg[%08lx] dma[%08x]\n", sgaddr, daddr); @@ -80,10 +80,10 @@ /* Verify the IOPTE points to the right page. */ paddr = iopte_val(*iopte) & IOPTE_PAGE; - if ((paddr + PAGE_OFFSET) != (sgaddr & PAGE_MASK)) { + if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) { printk("verify_one_map: IOPTE[%08lx] maps the " "wrong page, should be [%08lx]\n", - iopte_val(*iopte), (sgaddr & PAGE_MASK) - PAGE_OFFSET); + iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET); nents = -1; goto out; } @@ -91,10 +91,10 @@ /* If this SG crosses a page, adjust to that next page * boundary and loop. */ - if ((sgaddr & PAGE_MASK) ^ ((sgaddr + sglen - 1) & PAGE_MASK)) { + if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) { unsigned long next_page, diff; - next_page = (sgaddr + PAGE_SIZE) & PAGE_MASK; + next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK; diff = next_page - sgaddr; sgaddr += diff; daddr += diff; @@ -109,7 +109,7 @@ daddr += sglen; dlen -= sglen; - if (dlen > 0 && ((daddr & ~PAGE_MASK) == 0)) + if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) iopte++; sg++; @@ -175,7 +175,7 @@ int i; printk("verify_sglist: Crap, messed up mappings, dumping, iodma at %08x.\n", - (u32) (sg->dvma_address & PAGE_MASK)); + (u32) (sg->dvma_address & IO_PAGE_MASK)); for (i = 0; i < nents; i++) { printk("sg(%d): address(%p) length(%x) " "dma_address[%08x] dma_length[%08x]\n", @@ -189,13 +189,6 @@ } #endif -/* Two addresses are "virtually contiguous" if and only if: - * 1) They are equal, or... - * 2) They are both on a page boundry - */ -#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ - (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) - unsigned long prepare_sg(struct scatterlist *sg, int nents) { struct scatterlist *dma_sg = sg; @@ -204,7 +197,7 @@ prev = (unsigned long) sg->address; prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)sg->address & (PAGE_SIZE - 1UL)); + dent_addr = (u32) ((unsigned long)sg->address & (IO_PAGE_SIZE - 1UL)); while (--nents) { unsigned long addr; @@ -217,9 +210,9 @@ dent_addr = ((dent_addr + dent_len + - (PAGE_SIZE - 1UL)) >> PAGE_SHIFT); - dent_addr <<= PAGE_SHIFT; - dent_addr += addr & (PAGE_SIZE - 1UL); + (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT); + dent_addr <<= IO_PAGE_SHIFT; + dent_addr += addr & (IO_PAGE_SIZE - 1UL); dent_len = 0; } dent_len += sg->length; @@ -230,5 +223,5 @@ return ((unsigned long) dent_addr + (unsigned long) dent_len + - (PAGE_SIZE - 1UL)) >> PAGE_SHIFT; + (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT; } diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/iommu_common.h linux/arch/sparc64/kernel/iommu_common.h --- v2.4.9/linux/arch/sparc64/kernel/iommu_common.h Mon Dec 20 22:05:52 1999 +++ linux/arch/sparc64/kernel/iommu_common.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: iommu_common.h,v 1.1 1999/12/17 12:31:54 jj Exp $ +/* $Id: iommu_common.h,v 1.3 2001/08/24 19:36:58 kanoj Exp $ * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -10,6 +10,22 @@ #include #include #include + +/* + * These give mapping size of each iommu pte/tlb. + */ +#define IO_PAGE_SHIFT 13 +#define IO_PAGE_SIZE (1UL << IO_PAGE_SHIFT) +#define IO_PAGE_MASK (~(IO_PAGE_SIZE-1)) +#define IO_PAGE_ALIGN(addr) (((addr)+IO_PAGE_SIZE-1)&IO_PAGE_MASK) + +#define IO_TSB_ENTRIES (128*1024) +#define IO_TSB_SIZE (IO_TSB_ENTRIES * 8) + +/* + * This is the hardwired shift in the iotlb tag/data parts. + */ +#define IOMMU_PAGE_SHIFT 13 /* You are _strongly_ advised to enable the following debugging code * any time you make changes to the sg code below, run it for a while diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/itlb_base.S linux/arch/sparc64/kernel/itlb_base.S --- v2.4.9/linux/arch/sparc64/kernel/itlb_base.S Sun Nov 12 20:37:16 2000 +++ linux/arch/sparc64/kernel/itlb_base.S Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: itlb_base.S,v 1.10 2000/11/10 08:28:45 davem Exp $ +/* $Id: itlb_base.S,v 1.11 2001/08/17 04:55:09 kanoj Exp $ * itlb_base.S: Front end to ITLB miss replacement strategy. * This is included directly into the trap table. * @@ -6,8 +6,25 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff -#define VPTE_SHIFT (PAGE_SHIFT - 3) +#if PAGE_SHIFT == 13 +/* + * To compute vpte offset, we need to do ((addr >> 13) << 3), + * which can be optimized to (addr >> 10) if bits 10/11/12 can + * be guaranteed to be 0 ... mmu_context.h does guarantee this + * by only using 10 bits in the hwcontext value. + */ +#define CREATE_VPTE_OFFSET1(r1, r2) \ + srax r1, 10, r2 +#define CREATE_VPTE_OFFSET2(r1, r2) +#define CREATE_VPTE_NOP nop +#else /* PAGE_SHIFT */ +#define CREATE_VPTE_OFFSET1(r1, r2) \ + srax r1, PAGE_SHIFT, r2 +#define CREATE_VPTE_OFFSET2(r1, r2) \ + sllx r2, 3, r2 +#define CREATE_VPTE_NOP +#endif /* PAGE_SHIFT */ + /* Ways we can get here: * @@ -20,7 +37,8 @@ /* ITLB ** ICACHE line 1: Quick user TLB misses */ ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS - srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset + CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset + CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE 1: brgez,pn %g5, 3f ! Not valid, branch out nop ! Delay-slot @@ -58,7 +76,8 @@ nop nop nop - nop + CREATE_VPTE_NOP -#undef TAG_CONTEXT_BITS -#undef VPTE_SHIFT +#undef CREATE_VPTE_OFFSET1 +#undef CREATE_VPTE_OFFSET2 +#undef CREATE_VPTE_NOP diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c --- v2.4.9/linux/arch/sparc64/kernel/pci_iommu.c Thu May 24 15:00:58 2001 +++ linux/arch/sparc64/kernel/pci_iommu.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_iommu.c,v 1.14 2001/05/23 03:06:51 davem Exp $ +/* $Id: pci_iommu.c,v 1.15 2001/08/24 19:36:58 kanoj Exp $ * pci_iommu.c: UltraSparc PCI controller IOM/STC support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -121,7 +121,7 @@ while ((1UL << cnum) < npages) cnum++; - ent = (base << (32 - PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) + ent = (base << (32 - IO_PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) >> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits); /* If the global flush might not have caught this entry, @@ -184,7 +184,7 @@ void *ret; int npages; - size = PAGE_ALIGN(size); + size = IO_PAGE_ALIGN(size); order = get_order(size); if (order >= 10) return NULL; @@ -198,7 +198,7 @@ iommu = pcp->pbm->iommu; spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT); + iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); if (iopte == NULL) { spin_unlock_irqrestore(&iommu->lock, flags); free_pages(first_page, order); @@ -206,9 +206,9 @@ } *dma_addrp = (iommu->page_table_map_base + - ((iopte - iommu->page_table) << PAGE_SHIFT)); + ((iopte - iommu->page_table) << IO_PAGE_SHIFT)); ret = (void *) first_page; - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; @@ -218,17 +218,17 @@ IOPTE_WRITE | (first_page & IOPTE_PAGE)); iopte++; - first_page += PAGE_SIZE; + first_page += IO_PAGE_SIZE; } { int i; u32 daddr = *dma_addrp; - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; for (i = 0; i < npages; i++) { pci_iommu_write(iommu->iommu_flush, daddr); - daddr += PAGE_SIZE; + daddr += IO_PAGE_SIZE; } } @@ -245,11 +245,11 @@ iopte_t *iopte; unsigned long flags, order, npages, i, ctx; - npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; pcp = pdev->sysdata; iommu = pcp->pbm->iommu; iopte = iommu->page_table + - ((dvma - iommu->page_table_map_base) >> PAGE_SHIFT); + ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); @@ -286,7 +286,7 @@ pci_iommu_write(iommu->iommu_ctxflush, ctx); } else { for (i = 0; i < npages; i++) { - u32 daddr = dvma + (i << PAGE_SHIFT); + u32 daddr = dvma + (i << IO_PAGE_SHIFT); pci_iommu_write(iommu->iommu_flush, daddr); } @@ -321,8 +321,8 @@ BUG(); oaddr = (unsigned long)ptr; - npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; + npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; spin_lock_irqsave(&iommu->lock, flags); @@ -330,9 +330,9 @@ if (base == NULL) goto bad; bus_addr = (iommu->page_table_map_base + - ((base - iommu->page_table) << PAGE_SHIFT)); - ret = bus_addr | (oaddr & ~PAGE_MASK); - base_paddr = __pa(oaddr & PAGE_MASK); + ((base - iommu->page_table) << IO_PAGE_SHIFT)); + ret = bus_addr | (oaddr & ~IO_PAGE_MASK); + base_paddr = __pa(oaddr & IO_PAGE_MASK); ctx = 0; if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; @@ -343,7 +343,7 @@ if (direction != PCI_DMA_TODEVICE) iopte_protection |= IOPTE_WRITE; - for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE) + for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE) iopte_val(*base) = iopte_protection | base_paddr; spin_unlock_irqrestore(&iommu->lock, flags); @@ -372,15 +372,15 @@ iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK); - npages >>= PAGE_SHIFT; + npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU if (iopte_val(*base) == IOPTE_INVALID) printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", bus_addr, sz, __builtin_return_address(0)); #endif - bus_addr &= PAGE_MASK; + bus_addr &= IO_PAGE_MASK; spin_lock_irqsave(&iommu->lock, flags); @@ -404,7 +404,7 @@ pci_iommu_write(flushreg, ctx); } while(((long)pci_iommu_read(matchreg)) < 0L); } else { - for (i = 0; i < npages; i++, vaddr += PAGE_SIZE) + for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } @@ -432,9 +432,9 @@ unsigned long pteval = ~0UL; u32 dma_npages; - dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + + dma_npages = ((dma_sg->dvma_address & (IO_PAGE_SIZE - 1UL)) + dma_sg->dvma_length + - ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + ((u32)(IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; do { unsigned long offset; signed int len; @@ -449,15 +449,15 @@ tmp = (unsigned long) __pa(sg->address); len = sg->length; - if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { - pteval = tmp & PAGE_MASK; - offset = tmp & (PAGE_SIZE - 1UL); + if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { + pteval = tmp & IO_PAGE_MASK; + offset = tmp & (IO_PAGE_SIZE - 1UL); break; } - if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) { - pteval = (tmp + PAGE_SIZE) & PAGE_MASK; + if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { + pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; offset = 0UL; - len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL))); + len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); break; } sg++; @@ -466,8 +466,8 @@ pteval = iopte_protection | (pteval & IOPTE_PAGE); while (len > 0) { *iopte++ = __iopte(pteval); - pteval += PAGE_SIZE; - len -= (PAGE_SIZE - offset); + pteval += IO_PAGE_SIZE; + len -= (IO_PAGE_SIZE - offset); offset = 0; dma_npages--; } @@ -479,14 +479,14 @@ * adjusting pteval along the way. Stop when we * detect a page crossing event. */ - while ((pteval << (64 - PAGE_SHIFT)) != 0UL && + while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && pteval == __pa(sg->address) && ((pteval ^ - (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + (__pa(sg->address) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { pteval += sg->length; sg++; } - if ((pteval << (64 - PAGE_SHIFT)) == 0UL) + if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) pteval = ~0UL; } while (dma_npages != 0); dma_sg++; @@ -534,7 +534,7 @@ base = alloc_streaming_cluster(iommu, npages); if (base == NULL) goto bad; - dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT); + dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT); /* Step 3: Normalize DMA addresses. */ used = nelems; @@ -591,16 +591,16 @@ iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - bus_addr = sglist->dvma_address & PAGE_MASK; + bus_addr = sglist->dvma_address & IO_PAGE_MASK; for (i = 1; i < nelems; i++) if (sglist[i].dvma_length == 0) break; i--; - npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; + npages = (IO_PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> IO_PAGE_SHIFT; base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU if (iopte_val(*base) == IOPTE_INVALID) @@ -629,7 +629,7 @@ pci_iommu_write(flushreg, ctx); } while(((long)pci_iommu_read(matchreg)) < 0L); } else { - for (i = 0; i < npages; i++, vaddr += PAGE_SIZE) + for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, vaddr); } @@ -667,9 +667,9 @@ spin_lock_irqsave(&iommu->lock, flags); - npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK); - npages >>= PAGE_SHIFT; - bus_addr &= PAGE_MASK; + npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); + npages >>= IO_PAGE_SHIFT; + bus_addr &= IO_PAGE_MASK; /* Step 1: Record the context, if any. */ ctx = 0; @@ -678,7 +678,7 @@ iopte_t *iopte; iopte = iommu->page_table + - ((bus_addr - iommu->page_table_map_base)>>PAGE_SHIFT); + ((bus_addr - iommu->page_table_map_base)>>IO_PAGE_SHIFT); ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; } @@ -696,7 +696,7 @@ } else { unsigned long i; - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) + for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, bus_addr); } @@ -735,7 +735,7 @@ iopte_t *iopte; iopte = iommu->page_table + - ((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT); + ((sglist[0].dvma_address - iommu->page_table_map_base) >> IO_PAGE_SHIFT); ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; } @@ -754,14 +754,14 @@ unsigned long i, npages; u32 bus_addr; - bus_addr = sglist[0].dvma_address & PAGE_MASK; + bus_addr = sglist[0].dvma_address & IO_PAGE_MASK; for(i = 1; i < nelems; i++) if (!sglist[i].dvma_length) break; i--; - npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) + npages = (IO_PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> IO_PAGE_SHIFT; + for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE) pci_iommu_write(strbuf->strbuf_pflush, bus_addr); } diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c --- v2.4.9/linux/arch/sparc64/kernel/pci_psycho.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/pci_psycho.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.27 2001/08/12 13:18:23 davem Exp $ +/* $Id: pci_psycho.c,v 1.28 2001/08/24 19:36:58 kanoj Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -18,6 +18,7 @@ #include #include "pci_impl.h" +#include "iommu_common.h" /* All PSYCHO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter @@ -715,12 +716,12 @@ ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & PSYCHO_IOMMU_TAG_VPAGE) << PAGE_SHIFT); + (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", p->index, i, ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & PSYCHO_IOMMU_DATA_PPAGE) << PAGE_SHIFT); + (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } __psycho_check_stc_error(p, afsr, afar, type); @@ -1322,7 +1323,7 @@ * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. */ - tsbbase = __get_free_pages(GFP_KERNEL, 7); + tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE)); if (!tsbbase) { prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n"); prom_halt(); @@ -1331,7 +1332,7 @@ iommu->page_table_sz_bits = 17; iommu->page_table_map_base = 0xc0000000; iommu->dma_addr_mask = 0xffffffff; - memset((char *)tsbbase, 0, PAGE_SIZE << 7); + memset((char *)tsbbase, 0, IO_TSB_SIZE); /* We start with no consistent mappings. */ iommu->lowest_consistent_map = diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- v2.4.9/linux/arch/sparc64/kernel/pci_sabre.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/pci_sabre.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.38 2001/08/12 13:18:23 davem Exp $ +/* $Id: pci_sabre.c,v 1.39 2001/08/24 19:36:58 kanoj Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -19,6 +19,7 @@ #include #include "pci_impl.h" +#include "iommu_common.h" /* All SABRE registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter @@ -759,13 +760,13 @@ p->index, i, tag, type_string, ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), - ((tag & SABRE_IOMMUTAG_VPN) << PAGE_SHIFT)); + ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", p->index, i, data, ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), - ((data & SABRE_IOMMUDATA_PPN) << PAGE_SHIFT)); + ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); } } spin_unlock_irqrestore(&iommu->lock, flags); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c --- v2.4.9/linux/arch/sparc64/kernel/pci_schizo.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/pci_schizo.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pci_schizo.c,v 1.20 2001/08/12 13:18:23 davem Exp $ +/* $Id: pci_schizo.c,v 1.21 2001/08/24 19:36:58 kanoj Exp $ * pci_schizo.c: SCHIZO specific PCI controller support. * * Copyright (C) 2001 David S. Miller (davem@redhat.com) @@ -16,6 +16,7 @@ #include #include "pci_impl.h" +#include "iommu_common.h" /* All SCHIZO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter @@ -659,12 +660,12 @@ ((tag & SCHIZO_IOMMU_TAG_WRITE) ? 1 : 0), ((tag & SCHIZO_IOMMU_TAG_STREAM) ? 1 : 0), ((tag & SCHIZO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & SCHIZO_IOMMU_TAG_VPAGE) << PAGE_SHIFT); + (tag & SCHIZO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); printk("SCHIZO%d: PBM-%c IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", p->index, pbm_name, i, ((data & SCHIZO_IOMMU_DATA_VALID) ? 1 : 0), ((data & SCHIZO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & SCHIZO_IOMMU_DATA_PPAGE) << PAGE_SHIFT); + (data & SCHIZO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } __schizo_check_stc_error_pbm(pbm, type); @@ -1639,7 +1640,7 @@ * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. */ - tsbbase = __get_free_pages(GFP_KERNEL, 7); + tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE)); if (!tsbbase) { prom_printf("SCHIZO_IOMMU: Error, gfp(tsb) failed.\n"); prom_halt(); @@ -1648,7 +1649,7 @@ iommu->page_table_sz_bits = 17; iommu->page_table_map_base = 0xc0000000; iommu->dma_addr_mask = 0xffffffff; - memset((char *)tsbbase, 0, PAGE_SIZE << 7); + memset((char *)tsbbase, 0, IO_TSB_SIZE); /* We start with no consistent mappings. */ iommu->lowest_consistent_map = diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c --- v2.4.9/linux/arch/sparc64/kernel/sbus.c Thu May 24 15:00:58 2001 +++ linux/arch/sparc64/kernel/sbus.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.14 2001/05/23 03:06:51 davem Exp $ +/* $Id: sbus.c,v 1.16 2001/08/24 19:36:58 kanoj Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -37,7 +37,7 @@ #define ONE_GIG (1UL * 1024UL * 1024UL * 1024UL) #define CLUSTER_SIZE (ONE_GIG / NCLUSTERS) #define CLUSTER_MASK (CLUSTER_SIZE - 1) -#define CLUSTER_NPAGES (CLUSTER_SIZE >> PAGE_SHIFT) +#define CLUSTER_NPAGES (CLUSTER_SIZE >> IO_PAGE_SHIFT) #define MAP_BASE ((u32)0xc0000000) struct sbus_iommu { @@ -99,7 +99,7 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) { while (npages--) - upa_writeq(base + (npages << PAGE_SHIFT), + upa_writeq(base + (npages << IO_PAGE_SHIFT), iommu->iommu_regs + IOMMU_FLUSH); upa_readq(iommu->sbus_control_reg); } @@ -120,7 +120,7 @@ { iommu->strbuf_flushflag = 0UL; while (npages--) - upa_writeq(base + (npages << PAGE_SHIFT), + upa_writeq(base + (npages << IO_PAGE_SHIFT), iommu->strbuf_regs + STRBUF_PFLUSH); /* Whoopee cushion! */ @@ -191,8 +191,8 @@ cnum = 0; while ((1UL << cnum) < npages) cnum++; - ent = (base & CLUSTER_MASK) >> (PAGE_SHIFT + cnum); - iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum); + iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); iopte_val(*iopte) = 0UL; /* If the global flush might not have caught this entry, @@ -235,7 +235,7 @@ static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) { - iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) { iopte_t *walk = iopte + npages; @@ -266,7 +266,7 @@ if (size <= 0 || sdev == NULL || dvma_addr == NULL) return NULL; - size = PAGE_ALIGN(size); + size = IO_PAGE_ALIGN(size); order = get_order(size); if (order >= 10) return NULL; @@ -278,7 +278,7 @@ iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT); + iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); if (iopte == NULL) { spin_unlock_irqrestore(&iommu->lock, flags); free_pages(first_page, order); @@ -286,15 +286,15 @@ } /* Ok, we're committed at this point. */ - *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); ret = (void *) first_page; - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; while (npages--) { *iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | (__pa(first_page) & IOPTE_PAGE)); - first_page += PAGE_SIZE; + first_page += IO_PAGE_SIZE; } - iommu_flush(iommu, *dvma_addr, size >> PAGE_SHIFT); + iommu_flush(iommu, *dvma_addr, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); return ret; @@ -308,7 +308,7 @@ if (size <= 0 || sdev == NULL || cpu == NULL) return; - npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; iommu = sdev->bus->iommu; spin_lock_irq(&iommu->lock); @@ -333,25 +333,25 @@ BUG(); pbase = (unsigned long) ptr; - offset = (u32) (pbase & ~PAGE_MASK); - size = (PAGE_ALIGN(pbase + size) - (pbase & PAGE_MASK)); - pbase = (unsigned long) __pa(pbase & PAGE_MASK); + offset = (u32) (pbase & ~IO_PAGE_MASK); + size = (IO_PAGE_ALIGN(pbase + size) - (pbase & IO_PAGE_MASK)); + pbase = (unsigned long) __pa(pbase & IO_PAGE_MASK); spin_lock_irqsave(&iommu->lock, flags); - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; iopte = alloc_streaming_cluster(iommu, npages); if (iopte == NULL) goto bad; - dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); - npages = size >> PAGE_SHIFT; + dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); + npages = size >> IO_PAGE_SHIFT; iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE; if (dir != SBUS_DMA_TODEVICE) iopte_bits |= IOPTE_WRITE; while (npages--) { *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE)); - pbase += PAGE_SIZE; + pbase += IO_PAGE_SIZE; } - npages = size >> PAGE_SHIFT; + npages = size >> IO_PAGE_SHIFT; spin_unlock_irqrestore(&iommu->lock, flags); return (dma_base | offset); @@ -365,14 +365,14 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction) { struct sbus_iommu *iommu = sdev->bus->iommu; - u32 dma_base = dma_addr & PAGE_MASK; + u32 dma_base = dma_addr & IO_PAGE_MASK; unsigned long flags; - size = (PAGE_ALIGN(dma_addr + size) - dma_base); + size = (IO_PAGE_ALIGN(dma_addr + size) - dma_base); spin_lock_irqsave(&iommu->lock, flags); - free_streaming_cluster(iommu, dma_base, size >> PAGE_SHIFT); - strbuf_flush(iommu, dma_base, size >> PAGE_SHIFT); + free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT); + strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -385,9 +385,9 @@ unsigned long pteval = ~0UL; u32 dma_npages; - dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + + dma_npages = ((dma_sg->dvma_address & (IO_PAGE_SIZE - 1UL)) + dma_sg->dvma_length + - ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + ((u32)(IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT; do { unsigned long offset; signed int len; @@ -402,15 +402,15 @@ tmp = (unsigned long) __pa(sg->address); len = sg->length; - if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { - pteval = tmp & PAGE_MASK; - offset = tmp & (PAGE_SIZE - 1UL); + if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) { + pteval = tmp & IO_PAGE_MASK; + offset = tmp & (IO_PAGE_SIZE - 1UL); break; } - if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) { - pteval = (tmp + PAGE_SIZE) & PAGE_MASK; + if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) { + pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK; offset = 0UL; - len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL))); + len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL))); break; } sg++; @@ -419,8 +419,8 @@ pteval = ((pteval & IOPTE_PAGE) | iopte_bits); while (len > 0) { *iopte++ = __iopte(pteval); - pteval += PAGE_SIZE; - len -= (PAGE_SIZE - offset); + pteval += IO_PAGE_SIZE; + len -= (IO_PAGE_SIZE - offset); offset = 0; dma_npages--; } @@ -432,14 +432,14 @@ * adjusting pteval along the way. Stop when we * detect a page crossing event. */ - while ((pteval << (64 - PAGE_SHIFT)) != 0UL && + while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && pteval == __pa(sg->address) && ((pteval ^ - (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + (__pa(sg->address) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { pteval += sg->length; sg++; } - if ((pteval << (64 - PAGE_SHIFT)) == 0UL) + if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) pteval = ~0UL; } while (dma_npages != 0); dma_sg++; @@ -472,7 +472,7 @@ iopte = alloc_streaming_cluster(iommu, npages); if (iopte == NULL) goto bad; - dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + dma_base = MAP_BASE + ((iopte - iommu->page_table) << IO_PAGE_SHIFT); /* Normalize DVMA addresses. */ sgtmp = sg; @@ -516,18 +516,18 @@ return; } - dvma_base = sg[0].dvma_address & PAGE_MASK; + dvma_base = sg[0].dvma_address & IO_PAGE_MASK; for (i = 0; i < nents; i++) { if (sg[i].dvma_length == 0) break; } i--; - size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base; + size = IO_PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base; iommu = sdev->bus->iommu; spin_lock_irqsave(&iommu->lock, flags); - free_streaming_cluster(iommu, dvma_base, size >> PAGE_SHIFT); - strbuf_flush(iommu, dvma_base, size >> PAGE_SHIFT); + free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT); + strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -536,10 +536,10 @@ struct sbus_iommu *iommu = sdev->bus->iommu; unsigned long flags; - size = (PAGE_ALIGN(base + size) - (base & PAGE_MASK)); + size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK)); spin_lock_irqsave(&iommu->lock, flags); - strbuf_flush(iommu, base & PAGE_MASK, size >> PAGE_SHIFT); + strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -550,16 +550,16 @@ u32 base; int i; - base = sg[0].dvma_address & PAGE_MASK; + base = sg[0].dvma_address & IO_PAGE_MASK; for (i = 0; i < nents; i++) { if (sg[i].dvma_length == 0) break; } i--; - size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base; + size = IO_PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base; spin_lock_irqsave(&iommu->lock, flags); - strbuf_flush(iommu, base, size >> PAGE_SHIFT); + strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -1123,14 +1123,14 @@ * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. */ - tsb_base = __get_free_pages(GFP_ATOMIC, 7); + tsb_base = __get_free_pages(GFP_ATOMIC, get_order(IO_TSB_SIZE)); if (tsb_base == 0UL) { prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n"); prom_halt(); } iommu->page_table = (iopte_t *) tsb_base; - memset(iommu->page_table, 0, (PAGE_SIZE << 7)); + memset(iommu->page_table, 0, IO_TSB_SIZE); upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.4.9/linux/arch/sparc64/kernel/smp.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/smp.c Tue Aug 28 07:09:44 2001 @@ -702,7 +702,7 @@ int cpu = smp_processor_id(); start &= PAGE_MASK; - end &= PAGE_MASK; + end = PAGE_ALIGN(end); if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { mm->cpu_vm_mask = (1UL << cpu); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.9/linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.108 2001/06/05 03:39:50 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.110 2001/08/18 08:08:13 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -163,7 +163,9 @@ /* Atomic counter implementation. */ EXPORT_SYMBOL(__atomic_add); EXPORT_SYMBOL(__atomic_sub); +#ifdef CONFIG_SMP EXPORT_SYMBOL(atomic_dec_and_lock); +#endif /* Atomic bit operations. */ EXPORT_SYMBOL(___test_and_set_bit); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.4.9/linux/arch/sparc64/mm/fault.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/mm/fault.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.55 2001/08/09 20:18:43 davem Exp $ +/* $Id: fault.c,v 1.56 2001/08/27 18:42:07 kanoj Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -26,6 +26,16 @@ #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; + +void syscall_trace_entry(struct pt_regs *regs) +{ + printk("scall entry: %s[%d]/cpu%d: %d\n", current->comm, current->pid, smp_processor_id(), (int) regs->u_regs[UREG_G1]); +} + +void syscall_trace_exit(struct pt_regs *regs) +{ + printk("scall exit: %s[%d]/cpu%d: %d\n", current->comm, current->pid, smp_processor_id(), (int) regs->u_regs[UREG_G1]); +} /* Nice, simple, prom library does all the sweating for us. ;) */ unsigned long __init prom_probe_memory (void) diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.4.9/linux/arch/sparc64/mm/init.c Mon Aug 27 12:41:40 2001 +++ linux/arch/sparc64/mm/init.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.179 2001/08/08 07:52:00 davem Exp $ +/* $Id: init.c,v 1.186 2001/08/23 05:14:57 kanoj Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -202,10 +201,10 @@ struct linux_prom_translation *trans; unsigned long phys_page, tte_vaddr, tte_data; void (*remap_func)(unsigned long, unsigned long, int); - pgd_t *pgdp; - pmd_t *pmdp; + pmd_t *pmdp, *pmd; pte_t *ptep; int node, n, i, tsz; + extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2]; node = prom_finddevice("/virtual-memory"); n = prom_getproplen(node, "translations"); @@ -229,36 +228,39 @@ } n = n / sizeof(*trans); + /* + * The obp translations are saved based on 8k pagesize, since obp can use + * a mixture of pagesizes. Misses to the 0xf0000000 - 0x100000000, ie obp + * range, are handled in entry.S and do not use the vpte scheme (see rant + * in inherit_locked_prom_mappings()). + */ +#define OBP_PMD_SIZE 2048 +#define BASE_PAGE_SIZE 8192 + pmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, 0UL); + if (pmd == NULL) + early_pgtable_allocfail("pmd"); + memset(pmd, 0, OBP_PMD_SIZE); for (i = 0; i < n; i++) { unsigned long vaddr; if (trans[i].virt >= 0xf0000000 && trans[i].virt < 0x100000000) { for (vaddr = trans[i].virt; vaddr < trans[i].virt + trans[i].size; - vaddr += PAGE_SIZE) { + vaddr += BASE_PAGE_SIZE) { unsigned long val; - pgdp = pgd_offset(&init_mm, vaddr); - if (pgd_none(*pgdp)) { - pmdp = __alloc_bootmem(PMD_TABLE_SIZE, - PMD_TABLE_SIZE, - 0UL); - if (pmdp == NULL) - early_pgtable_allocfail("pmd"); - memset(pmdp, 0, PMD_TABLE_SIZE); - pgd_set(pgdp, pmdp); - } - pmdp = pmd_offset(pgdp, vaddr); + pmdp = pmd + ((vaddr >> 23) & 0x7ff); if (pmd_none(*pmdp)) { - ptep = __alloc_bootmem(PTE_TABLE_SIZE, - PTE_TABLE_SIZE, + ptep = __alloc_bootmem(BASE_PAGE_SIZE, + BASE_PAGE_SIZE, 0UL); if (ptep == NULL) early_pgtable_allocfail("pte"); - memset(ptep, 0, PTE_TABLE_SIZE); + memset(ptep, 0, BASE_PAGE_SIZE); pmd_set(pmdp, ptep); } - ptep = pte_offset(pmdp, vaddr); + ptep = (pte_t *)pmd_page(*pmdp) + + ((vaddr >> 13) & 0x3ff); val = trans[i].data; @@ -267,10 +269,17 @@ val &= ~0x0003fe0000000000UL; set_pte (ptep, __pte(val | _PAGE_MODIFIED)); - trans[i].data += PAGE_SIZE; + trans[i].data += BASE_PAGE_SIZE; } } } + phys_page = __pa(pmd); + obp_iaddr_patch[0] |= (phys_page >> 10); + obp_iaddr_patch[1] |= (phys_page & 0x3ff); + flushi((long)&obp_iaddr_patch[0]); + obp_daddr_patch[0] |= (phys_page >> 10); + obp_daddr_patch[1] |= (phys_page & 0x3ff); + flushi((long)&obp_daddr_patch[0]); /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); diff -u --recursive --new-file v2.4.9/linux/arch/sparc64/mm/modutil.c linux/arch/sparc64/mm/modutil.c --- v2.4.9/linux/arch/sparc64/mm/modutil.c Thu Apr 12 12:10:25 2001 +++ linux/arch/sparc64/mm/modutil.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: modutil.c,v 1.8 2001/04/04 00:49:39 davem Exp $ +/* $Id: modutil.c,v 1.9 2001/08/14 22:10:56 davem Exp $ * arch/sparc64/mm/modutil.c * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -10,7 +10,10 @@ #include #include -#include + +#define MODULES_VADDR 0x0000000001000000ULL /* Where to map modules */ +#define MODULES_LEN 0x000000007f000000ULL +#define MODULES_END 0x0000000080000000ULL static struct vm_struct * modvmlist = NULL; diff -u --recursive --new-file v2.4.9/linux/drivers/atm/Makefile linux/drivers/atm/Makefile --- v2.4.9/linux/drivers/atm/Makefile Mon Mar 26 15:36:30 2001 +++ linux/drivers/atm/Makefile Mon Aug 27 09:01:33 2001 @@ -25,6 +25,7 @@ obj-$(CONFIG_ATM_AMBASSADOR) += ambassador.o obj-$(CONFIG_ATM_TCP) += atmtcp.o obj-$(CONFIG_ATM_IA) += iphase.o suni.o +obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o ifeq ($(CONFIG_ATM_FORE200E_PCA),y) FORE200E_FW_OBJS += fore200e_pca_fw.o diff -u --recursive --new-file v2.4.9/linux/drivers/atm/firestream.c linux/drivers/atm/firestream.c --- v2.4.9/linux/drivers/atm/firestream.c Wed Apr 11 19:02:30 2001 +++ linux/drivers/atm/firestream.c Mon Aug 27 09:01:33 2001 @@ -295,6 +295,7 @@ static int fs_keystream = 0; +static int fs_maxphy = 1; #ifdef DEBUG /* I didn't forget to set this to zero before shipping. Hit me with a stick @@ -308,6 +309,7 @@ #ifdef DEBUG MODULE_PARM(fs_debug, "i"); #endif +MODULE_PARM(fs_maxphy, "i"); MODULE_PARM(loopback, "i"); MODULE_PARM(num, "i"); MODULE_PARM(fs_keystream, "i"); @@ -866,6 +868,7 @@ int bfp; int to; unsigned short tmc0; + int uaddr; func_enter (); @@ -908,6 +911,9 @@ txtp = &atm_vcc->qos.txtp; rxtp = &atm_vcc->qos.rxtp; + /* XXX Use VPI? How many bits? Which bits? */ + uaddr = atm_vcc->dev->number - dev->start_number; + if (!test_bit(ATM_VF_PARTIAL, &atm_vcc->flags)) { if (IS_FS50(dev)) { /* Increment the channel numer: take a free one next time. */ @@ -1012,7 +1018,7 @@ tc->TMC[2] = 0; /* Unused */ tc->TMC[3] = 0; /* Unused */ - tc->spec = 0; /* UTOPIA address, UDF, HEC: Unused -> 0 */ + tc->spec = uaddr << 16; /* UTOPIA address, UDF, HEC: Unused -> 0 */ tc->rtag[0] = 0; /* What should I do with routing tags??? -- Not used -- AS -- Thanks -- REW*/ tc->rtag[1] = 0; @@ -1081,7 +1087,7 @@ submit_command (dev, &dev->hp_txq, QE_CMD_REG_WR | QE_CMD_IMM_INQ, 0x80 + vcc->channo, - (vpi << 16) | vci, 0 ); /* XXX -- Use defines. */ + (uaddr << 28) | (vpi << 16) | vci, 0 ); /* XXX -- Use defines. */ } submit_command (dev, &dev->hp_txq, QE_CMD_RX_EN | QE_CMD_IMM_INQ | vcc->channo, @@ -1772,8 +1778,10 @@ if (IS_FS50 (dev)) { write_fs (dev, RAS0, RAS0_DCD_XHLT); - dev->atm_dev->ci_range.vpi_bits = 12; - dev->atm_dev->ci_range.vci_bits = 16; + for (i=0;iatm_dev[i]->ci_range.vpi_bits = 12; + dev->atm_dev[i]->ci_range.vci_bits = 16; + } dev->nchannels = FS50_NR_CHANNELS; } else { write_fs (dev, RAS0, RAS0_DCD_XHLT @@ -1781,8 +1789,10 @@ | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL)); /* We can chose the split arbitarily. We might be able to support more. Whatever. This should do for now. */ - dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS; - dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS; + for (i=0;iatm_dev[i]->ci_range.vpi_bits = FS155_VPI_BITS; + dev->atm_dev[i]->ci_range.vci_bits = FS155_VCI_BITS; + } /* Address bits we can't use should be compared to 0. */ write_fs (dev, RAC, 0); @@ -1817,9 +1827,14 @@ } memset (dev->tx_inuse, 0, dev->nchannels / 8); - /* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for both */ - /* -- RAS2 : FS50 only: Default is OK. */ + if (IS_FS50 (dev)) { + /* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for FS155, FS50/multiphy needs the maxPHY set... */ + write_fs (dev, RAS1, (fs_maxphy - 1) * RAS1_UTREG); + /* -- RAS2 : FS50 only: Default is OK. */ + /* Enable selecting for Utopia address for multiphy configs. */ + write_fs (dev, RAS2, RAS2_USEL); + } /* DMAMODE, default should be OK. -- REW */ write_fs (dev, DMAMR, DMAMR_TX_MODE_FULL); @@ -1888,7 +1903,8 @@ add_timer (&dev->timer); #endif - dev->atm_dev->dev_data = dev; + for (i=0;iatm_dev[i]->dev_data = dev; func_exit (); return 0; @@ -1897,9 +1913,9 @@ static int __init firestream_init_one (struct pci_dev *pci_dev, const struct pci_device_id *ent) { - struct atm_dev *atm_dev; struct fs_dev *fs_dev; - + int i; + if (pci_enable_device(pci_dev)) goto err_out; @@ -1910,13 +1926,17 @@ goto err_out; memset (fs_dev, 0, sizeof (struct fs_dev)); - - atm_dev = atm_dev_register("fs", &ops, -1, NULL); - if (!atm_dev) - goto err_out_free_fs_dev; - + + for (i=0;iatm_dev[i] = atm_dev_register("fs", &ops, -1, NULL); + if (!fs_dev->atm_dev[i]) + goto err_out_free_atm_dev; + } + /* XXX if another device is registering atm devices at the same time + we get confusion. */ + fs_dev->start_number = fs_dev->atm_dev[0]->number; + fs_dev->pci_dev = pci_dev; - fs_dev->atm_dev = atm_dev; fs_dev->flags = ent->driver_data; if (fs_init(fs_dev)) @@ -1927,7 +1947,8 @@ return 0; err_out_free_atm_dev: - atm_dev_deregister(atm_dev); + for (i--;i >= 0;i--) + atm_dev_deregister(fs_dev->atm_dev[i]); err_out_free_fs_dev: kfree(fs_dev); err_out: @@ -2002,7 +2023,9 @@ free_irq (dev->irq, dev); del_timer (&dev->timer); - atm_dev_deregister(dev->atm_dev); + for (i=0;iatm_dev[i]); + free_queue (dev, &dev->hp_txq); free_queue (dev, &dev->lp_txq); free_queue (dev, &dev->tx_relq); diff -u --recursive --new-file v2.4.9/linux/drivers/atm/firestream.h linux/drivers/atm/firestream.h --- v2.4.9/linux/drivers/atm/firestream.h Wed Apr 11 19:02:30 2001 +++ linux/drivers/atm/firestream.h Mon Aug 27 09:01:33 2001 @@ -345,13 +345,15 @@ #define CELLOSCONF_COST (0x1 << 0) /* Bits? */ - #define RAS0 0x1bc #define RAS0_DCD_XHLT (0x1 << 31) #define RAS0_VPSEL (0x1 << 16) #define RAS0_VCSEL (0x1 << 0) +#define RAS1 0x1c0 +#define RAS1_UTREG (0x1 << 5) + #define DMAMR 0x1cc #define DMAMR_TX_MODE_FULL (0x0 << 0) @@ -360,6 +362,14 @@ +#define RAS2 0x280 + +#define RAS2_NNI (0x1 << 0) +#define RAS2_USEL (0x1 << 1) +#define RAS2_UBS (0x1 << 2) + + + struct fs_transmit_config { u32 flags; u32 atm_hdr; @@ -456,6 +466,7 @@ int n; }; +#define MAX_PHY 0x20 struct fs_dev { struct fs_dev *next; /* other FS devices */ @@ -463,8 +474,9 @@ unsigned char irq; /* IRQ */ struct pci_dev *pci_dev; /* PCI stuff */ - struct atm_dev *atm_dev; + struct atm_dev *atm_dev[MAX_PHY]; struct timer_list timer; + int start_number; unsigned long hw_base; /* mem base address */ unsigned long base; /* Mapping of base address */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h --- v2.4.9/linux/drivers/char/agp/agp.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/agp/agp.h Mon Aug 27 07:40:33 2001 @@ -101,6 +101,7 @@ int num_aperture_sizes; int num_of_masks; int capndx; + int cant_use_aperture; /* Links to driver specific functions */ diff -u --recursive --new-file v2.4.9/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- v2.4.9/linux/drivers/char/agp/agpgart_be.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/agp/agpgart_be.c Mon Aug 27 07:40:33 2001 @@ -305,6 +305,9 @@ void agp_copy_info(agp_kern_info * info) { + unsigned long page_mask = 0; + int i; + memset(info, 0, sizeof(agp_kern_info)); if (agp_bridge.type == NOT_SUPPORTED) { info->chipset = agp_bridge.type; @@ -319,6 +322,12 @@ info->aper_size = agp_return_size(); info->max_memory = agp_bridge.max_memory_agp; info->current_memory = atomic_read(&agp_bridge.current_memory_agp); + info->cant_use_aperture = agp_bridge.cant_use_aperture; + + for(i = 0; i < agp_bridge.num_of_masks; i++) + page_mask |= agp_bridge.mask_memory(page_mask, i); + + info->page_mask = ~page_mask; } /* End - Routine to copy over information structure */ @@ -1083,6 +1092,7 @@ agp_bridge.free_by_type = intel_i810_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; } @@ -1275,6 +1285,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1305,6 +1316,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1335,6 +1347,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1452,6 +1465,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -1563,6 +1577,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; } @@ -1938,6 +1953,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -2181,6 +2197,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = ali_alloc_page; agp_bridge.agp_destroy_page = ali_destroy_page; + agp_bridge.cant_use_aperture = 0; return 0; @@ -2766,6 +2783,7 @@ agp_bridge.free_by_type = agp_generic_free_by_type; agp_bridge.agp_alloc_page = agp_generic_alloc_page; agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.cant_use_aperture = 0; pci_read_config_dword(agp_bridge.dev, SVWRKS_APSIZE, diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/ati_pcigart.h linux/drivers/char/drm/ati_pcigart.h --- v2.4.9/linux/drivers/char/drm/ati_pcigart.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/ati_pcigart.h Mon Aug 27 13:22:50 2001 @@ -72,8 +72,6 @@ int i; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !address ) return; - page = virt_to_page( address ); for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) { @@ -84,23 +82,40 @@ free_pages( address, ATI_PCIGART_TABLE_ORDER ); } -unsigned long DRM(ati_pcigart_init)( drm_device_t *dev ) +int DRM(ati_pcigart_init)( drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr) { drm_sg_mem_t *entry = dev->sg; - unsigned long address; + unsigned long address = 0; unsigned long pages; - u32 *pci_gart, page_base; - int i, j; + u32 *pci_gart, page_base, bus_address = 0; + int i, j, ret = 0; if ( !entry ) { DRM_ERROR( "no scatter/gather memory!\n" ); - return 0; + goto done; } address = DRM(ati_alloc_pcigart_table)(); if ( !address ) { DRM_ERROR( "cannot allocate PCI GART page!\n" ); - return 0; + goto done; + } + + if ( !dev->pdev ) { + DRM_ERROR( "PCI device unknown!\n" ); + goto done; + } + + bus_address = pci_map_single(dev->pdev, (void *)address, + ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, + PCI_DMA_TODEVICE); + if (bus_address == 0) { + DRM_ERROR( "unable to map PCIGART pages!\n" ); + DRM(ati_free_pcigart_table)( address ); + address = 0; + goto done; } pci_gart = (u32 *)address; @@ -111,28 +126,72 @@ memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) ); for ( i = 0 ; i < pages ; i++ ) { - page_base = page_to_bus( entry->pagelist[i] ); + /* we need to support large memory configurations */ + entry->busaddr[i] = pci_map_single(dev->pdev, + page_address( entry->pagelist[i] ), + PAGE_SIZE, + PCI_DMA_TODEVICE); + if (entry->busaddr[i] == 0) { + DRM_ERROR( "unable to map PCIGART pages!\n" ); + DRM(ati_pcigart_cleanup)( dev, address, bus_address ); + address = 0; + bus_address = 0; + goto done; + } + page_base = (u32) entry->busaddr[i]; + for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { *pci_gart++ = cpu_to_le32( page_base ); page_base += ATI_PCIGART_PAGE_SIZE; } } + ret = 1; + #if __i386__ asm volatile ( "wbinvd" ::: "memory" ); #else mb(); #endif - return address; +done: + *addr = address; + *bus_addr = bus_address; + return ret; } -int DRM(ati_pcigart_cleanup)( unsigned long address ) +int DRM(ati_pcigart_cleanup)( drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr) { + drm_sg_mem_t *entry = dev->sg; + unsigned long pages; + int i; - if ( address ) { - DRM(ati_free_pcigart_table)( address ); + /* we need to support large memory configurations */ + if ( !entry ) { + DRM_ERROR( "no scatter/gather memory!\n" ); + return 0; + } + + if ( bus_addr ) { + pci_unmap_single(dev->pdev, bus_addr, + ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, + PCI_DMA_TODEVICE); + + pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) + ? entry->pages : ATI_MAX_PCIGART_PAGES; + + for ( i = 0 ; i < pages ; i++ ) { + if ( !entry->busaddr[i] ) break; + pci_unmap_single(dev->pdev, entry->busaddr[i], + PAGE_SIZE, PCI_DMA_TODEVICE); + } + } + + if ( addr ) { + DRM(ati_free_pcigart_table)( addr ); } - return 0; + return 1; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h --- v2.4.9/linux/drivers/char/drm/drmP.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drmP.h Mon Aug 27 13:22:50 2001 @@ -76,6 +76,17 @@ #include #include "drm.h" +/* page_to_bus for earlier kernels, not optimal in all cases */ +#ifndef page_to_bus +#define page_to_bus(page) ((unsigned int)(virt_to_bus(page_address(page)))) +#endif + +/* We just use virt_to_bus for pci_map_single on older kernels */ +#if LINUX_VERSION_CODE < 0x020400 +#define pci_map_single(hwdev, ptr, size, direction) virt_to_bus(ptr) +#define pci_unmap_single(hwdev, dma_addr, size, direction) +#endif + /* DRM template customization defaults */ #ifndef __HAVE_AGP @@ -616,6 +627,8 @@ int acquired; unsigned long base; int agp_mtrr; + int cant_use_aperture; + unsigned long page_mask; } drm_agp_head_t; #endif @@ -624,6 +637,7 @@ void *virtual; int pages; struct page **pagelist; + dma_addr_t *busaddr; } drm_sg_mem_t; typedef struct drm_sigdata { @@ -714,6 +728,7 @@ #if __REALLY_HAVE_AGP drm_agp_head_t *agp; #endif + struct pci_dev *pdev; #ifdef __alpha__ #if LINUX_VERSION_CODE < 0x020403 struct pci_controler *hose; @@ -1018,8 +1033,12 @@ #endif /* ATI PCIGART support (ati_pcigart.h) */ -extern unsigned long DRM(ati_pcigart_init)(drm_device_t *dev); -extern int DRM(ati_pcigart_cleanup)(unsigned long address); +extern int DRM(ati_pcigart_init)(drm_device_t *dev, + unsigned long *addr, + dma_addr_t *bus_addr); +extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev, + unsigned long addr, + dma_addr_t bus_addr); #endif /* __KERNEL__ */ #endif diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_agpsupport.h linux/drivers/char/drm/drm_agpsupport.h --- v2.4.9/linux/drivers/char/drm/drm_agpsupport.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drm_agpsupport.h Mon Aug 27 13:22:50 2001 @@ -316,6 +316,14 @@ default: head->chipset = "Unknown"; break; } +#if LINUX_VERSION_CODE <= 0x020408 + head->cant_use_aperture = 0; + head->page_mask = ~(0xfff); +#else + head->cant_use_aperture = head->agp_info.cant_use_aperture; + head->page_mask = head->agp_info.page_mask; +#endif + DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n", head->agp_info.version.major, head->agp_info.version.minor, diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_ioctl.h linux/drivers/char/drm/drm_ioctl.h --- v2.4.9/linux/drivers/char/drm/drm_ioctl.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/drm_ioctl.h Mon Aug 27 13:22:50 2001 @@ -98,7 +98,6 @@ } sprintf(dev->devname, "%s@%s", dev->name, dev->unique); -#ifdef __alpha__ do { struct pci_dev *pci_dev; int b, d, f; @@ -114,10 +113,13 @@ if (*p) break; pci_dev = pci_find_slot(b, PCI_DEVFN(d,f)); - if (pci_dev) - dev->hose = pci_dev->sysdata; - } while(0); + if (pci_dev) { + dev->pdev = pci_dev; +#ifdef __alpha__ + dev->hose = pci_dev->sysdata; #endif + } + } while(0); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_scatter.h linux/drivers/char/drm/drm_scatter.h --- v2.4.9/linux/drivers/char/drm/drm_scatter.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/drm_scatter.h Mon Aug 27 13:22:50 2001 @@ -47,12 +47,15 @@ vfree( entry->virtual ); + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); + sizeof(*entry), + DRM_MEM_SGLISTS ); } int DRM(sg_alloc)( struct inode *inode, struct file *filp, @@ -93,16 +96,31 @@ DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); return -ENOMEM; } - memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); + + entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + if ( !entry->busaddr ) { + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); + return -ENOMEM; + } + memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); if ( !entry->virtual ) { + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); + sizeof(*entry), + DRM_MEM_SGLISTS ); return -ENOMEM; } diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/drm_vm.h linux/drivers/char/drm/drm_vm.h --- v2.4.9/linux/drivers/char/drm/drm_vm.h Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/drm_vm.h Mon Aug 27 13:22:50 2001 @@ -67,6 +67,70 @@ int write_access) #endif { +#if __REALLY_HAVE_AGP + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map = NULL; + drm_map_list_t *r_list; + struct list_head *list; + + /* + * Find the right map + */ + + if(!dev->agp->cant_use_aperture) goto vm_nopage_error; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *)list; + map = r_list->map; + if (!map) continue; + if (map->offset == VM_OFFSET(vma)) break; + } + + if (map && map->type == _DRM_AGP) { + unsigned long offset = address - vma->vm_start; + unsigned long baddr = VM_OFFSET(vma) + offset; + struct drm_agp_mem *agpmem; + struct page *page; + +#if __alpha__ + /* + * Adjust to a bus-relative address + */ + baddr -= dev->hose->mem_space->start; +#endif + + /* + * It's AGP memory - find the real physical page to map + */ + for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { + if (agpmem->bound <= baddr && + agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) + break; + } + + if (!agpmem) goto vm_nopage_error; + + /* + * Get the page, inc the use count, and return it + */ + offset = (baddr - agpmem->bound) >> PAGE_SHIFT; + agpmem->memory->memory[offset] &= dev->agp->page_mask; + page = virt_to_page(__va(agpmem->memory->memory[offset])); + get_page(page); + + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n", + baddr, __va(agpmem->memory->memory[offset]), offset); + +#if LINUX_VERSION_CODE < 0x020317 + return page_address(page); +#else + return page; +#endif + } +vm_nopage_error: +#endif /* __REALLY_HAVE_AGP */ + return NOPAGE_SIGBUS; /* Disallow mremap */ } @@ -220,24 +284,27 @@ drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; drm_device_dma_t *dma = dev->dma; - unsigned long physical; unsigned long offset; - unsigned long page; + unsigned long page_nr; + struct page *page; if (!dma) return NOPAGE_SIGBUS; /* Error */ if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ - page = offset >> PAGE_SHIFT; - physical = dma->pagelist[page] + (offset & (~PAGE_MASK)); - atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */ + page_nr = offset >> PAGE_SHIFT; + page = virt_to_page((dma->pagelist[page_nr] + + (offset & (~PAGE_MASK)))); - DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical); + get_page(page); + + DRM_DEBUG("0x%08lx (page %lu) => 0x%08x\n", address, page_nr, + page_to_bus(page)); #if LINUX_VERSION_CODE < 0x020317 - return physical; + return page_address(page); #else - return virt_to_page(physical); + return page; #endif } @@ -274,10 +341,10 @@ map_offset = map->offset - dev->sg->handle; page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; - atomic_inc(&page->count); /* Dec. by kernel */ + get_page(page); #if LINUX_VERSION_CODE < 0x020317 - return (unsigned long)virt_to_phys(page->virtual); + return page_address(page); #else return page; #endif @@ -435,9 +502,20 @@ } switch (map->type) { + case _DRM_AGP: +#if defined(__alpha__) + /* + * On Alpha we can't talk to bus dma address from the + * CPU, so for memory of type DRM_AGP, we'll deal with + * sorting out the real physical pages and mappings + * in nopage() + */ + vma->vm_ops = &DRM(vm_ops); + break; +#endif + /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: - case _DRM_AGP: if (VM_OFFSET(vma) >= __pa(high_memory)) { #if defined(__i386__) if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/mga_drv.h linux/drivers/char/drm/mga_drv.h --- v2.4.9/linux/drivers/char/drm/mga_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/mga_drv.h Mon Aug 27 07:40:33 2001 @@ -145,14 +145,28 @@ #define mga_flush_write_combine() mb() -#define MGA_BASE( reg ) ((u32)(dev_priv->mmio->handle)) +#define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle)) #define MGA_ADDR( reg ) (MGA_BASE(reg) + reg) #define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg ) +#define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg ) + +#ifdef __alpha__ +#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) +#define MGA_WRITE( reg, val ) do { wmb(); MGA_DEREF( reg ) = val; } while (0) +#define MGA_WRITE8( reg, val ) do { wmb(); MGA_DEREF8( reg ) = val; } while (0) + +static inline u32 _MGA_READ(u32 *addr) +{ + mb(); + return *(volatile u32 *)addr; +} + +#else #define MGA_READ( reg ) MGA_DEREF( reg ) #define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0) -#define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg ) #define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0) +#endif #define DWGREG0 0x1c00 #define DWGREG0_END 0x1dff diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/r128_cce.c linux/drivers/char/drm/r128_cce.c --- v2.4.9/linux/drivers/char/drm/r128_cce.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/r128_cce.c Mon Aug 27 07:40:33 2001 @@ -351,11 +351,10 @@ page_ofs = tmp_ofs >> PAGE_SHIFT; R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, - page_to_bus(entry->pagelist[page_ofs])); - - DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", - page_to_bus(entry->pagelist[page_ofs]), - entry->handle + tmp_ofs ); + entry->busaddr[page_ofs]); + DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", + entry->busaddr[page_ofs], + entry->handle + tmp_ofs ); } /* Set watermark control */ @@ -599,15 +598,14 @@ dev_priv->sarea_priv->last_dispatch ); if ( dev_priv->is_pci ) { - dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev ); - if ( !dev_priv->phys_pci_gart ) { + if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, + &dev_priv->bus_pci_gart) ) { DRM_ERROR( "failed to init PCI GART!\n" ); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); return -ENOMEM; } - R128_WRITE( R128_PCI_GART_PAGE, - virt_to_bus( (void *)dev_priv->phys_pci_gart ) ); + R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart ); } r128_cce_init_ring_buffer( dev, dev_priv ); @@ -629,6 +627,11 @@ DRM_IOREMAPFREE( dev_priv->cce_ring ); DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); + } else { + if (!DRM(ati_pcigart_cleanup)( dev, + dev_priv->phys_pci_gart, + dev_priv->bus_pci_gart )) + DRM_ERROR( "failed to cleanup PCI GART!\n" ); } DRM(free)( dev->dev_private, sizeof(drm_r128_private_t), diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/r128_drv.h linux/drivers/char/drm/r128_drv.h --- v2.4.9/linux/drivers/char/drm/r128_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/r128_drv.h Mon Aug 27 07:40:33 2001 @@ -72,6 +72,7 @@ int usec_timeout; int is_pci; unsigned long phys_pci_gart; + dma_addr_t bus_pci_gart; unsigned long cce_buffers_offset; atomic_t idle_count; diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/radeon_cp.c linux/drivers/char/drm/radeon_cp.c --- v2.4.9/linux/drivers/char/drm/radeon_cp.c Mon Aug 27 12:41:40 2001 +++ linux/drivers/char/drm/radeon_cp.c Mon Aug 27 07:40:33 2001 @@ -624,10 +624,9 @@ page_ofs = tmp_ofs >> PAGE_SHIFT; RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, - page_to_bus(entry->pagelist[page_ofs])); - + entry->busaddr[page_ofs]); DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - page_to_bus(entry->pagelist[page_ofs]), + entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } @@ -929,8 +928,8 @@ dev_priv->sarea_priv->last_clear ); if ( dev_priv->is_pci ) { - dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev ); - if ( !dev_priv->phys_pci_gart ) { + if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, + &dev_priv->bus_pci_gart)) { DRM_ERROR( "failed to init PCI GART!\n" ); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); @@ -944,8 +943,7 @@ /* set PCI GART page-table base address */ - RADEON_WRITE( RADEON_AIC_PT_BASE, - virt_to_bus( (void *)dev_priv->phys_pci_gart ) ); + RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart ); /* set address range for PCI address translate */ @@ -990,6 +988,11 @@ DRM_IOREMAPFREE( dev_priv->cp_ring ); DRM_IOREMAPFREE( dev_priv->ring_rptr ); DRM_IOREMAPFREE( dev_priv->buffers ); + } else { + if (!DRM(ati_pcigart_cleanup)( dev, + dev_priv->phys_pci_gart, + dev_priv->bus_pci_gart )) + DRM_ERROR( "failed to cleanup PCI GART!\n" ); } DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/radeon_drv.h linux/drivers/char/drm/radeon_drv.h --- v2.4.9/linux/drivers/char/drm/radeon_drv.h Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/radeon_drv.h Mon Aug 27 07:40:33 2001 @@ -84,6 +84,7 @@ int usec_timeout; int is_pci; unsigned long phys_pci_gart; + dma_addr_t bus_pci_gart; atomic_t idle_count; diff -u --recursive --new-file v2.4.9/linux/drivers/char/drm/tdfx_drv.c linux/drivers/char/drm/tdfx_drv.c --- v2.4.9/linux/drivers/char/drm/tdfx_drv.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/char/drm/tdfx_drv.c Mon Aug 27 07:40:33 2001 @@ -44,13 +44,30 @@ #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 +#ifndef PCI_VENDOR_ID_3DFX +#define PCI_VENDOR_ID_3DFX 0x121A +#endif #ifndef PCI_DEVICE_ID_3DFX_VOODOO5 #define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 #endif +#ifndef PCI_DEVICE_ID_3DFX_VOODOO4 +#define PCI_DEVICE_ID_3DFX_VOODOO4 0x0007 +#endif +#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_3000 /* Voodoo3 3000 */ +#define PCI_DEVICE_ID_3DFX_VOODOO3_3000 0x0005 +#endif +#ifndef PCI_DEVICE_ID_3DFX_VOODOO3_2000 /* Voodoo3 3000 */ +#define PCI_DEVICE_ID_3DFX_VOODOO3_2000 0x0004 +#endif +#ifndef PCI_DEVICE_ID_3DFX_BANSHEE +#define PCI_DEVICE_ID_3DFX_BANSHEE 0x0003 +#endif static drm_pci_list_t DRM(idlist)[] = { { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE }, - { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_2000 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3_3000 }, + { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO4 }, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 }, { 0, 0 } }; diff -u --recursive --new-file v2.4.9/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.4.9/linux/drivers/char/pc_keyb.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/pc_keyb.c Tue Aug 28 07:09:44 2001 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -602,7 +603,7 @@ return 1; } -int pckbd_rate(struct kbd_repeat *rep) +static int pckbd_rate(struct kbd_repeat *rep) { if (rep == NULL) return -EINVAL; @@ -834,6 +835,8 @@ #if defined CONFIG_PSMOUSE psaux_init(); #endif + + kbd_rate = pckbd_rate; /* Ok, finally allocate the IRQ, and off we go.. */ kbd_request_irq(keyboard_interrupt); diff -u --recursive --new-file v2.4.9/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.4.9/linux/drivers/char/vt.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/char/vt.c Tue Aug 28 07:09:44 2001 @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -145,8 +144,13 @@ #endif -void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound; +int _kbd_rate(struct kbd_repeat *rep) +{ + return -EINVAL; +} +void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound; +int (*kbd_rate)(struct kbd_repeat *rep) = _kbd_rate; #define i (tmp.kb_index) #define s (tmp.kb_table) @@ -504,7 +508,6 @@ { struct kbd_repeat kbrep; - if (!kbd_rate) return( -EINVAL ); if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff -u --recursive --new-file v2.4.9/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c --- v2.4.9/linux/drivers/i2o/i2o_block.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/i2o/i2o_block.c Mon Aug 27 14:20:21 2001 @@ -1195,9 +1195,6 @@ if(!dev->i2odev) return 0; - /* Sync the device so we don't get errors */ - fsync_dev(inode->i_rdev); - if (dev->refcnt <= 0) printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt); dev->refcnt--; diff -u --recursive --new-file v2.4.9/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c --- v2.4.9/linux/drivers/ide/via82cxxx.c Mon Aug 27 12:41:41 2001 +++ linux/drivers/ide/via82cxxx.c Mon Aug 27 07:48:29 2001 @@ -1,5 +1,5 @@ /* - * $Id: via82cxxx.c,v 3.23 2001/03/09 09:30:00 vojtech Exp $ + * $Id: via82cxxx.c,v 3.26 2001/08/17 12:03:00 vojtech Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik * @@ -88,7 +88,6 @@ #define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */ #define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ #define VIA_SET_THRESH 0x080 /* Needs to have FIFO thresholds set */ -#define VIA_BAD_PIO 0x100 /* Always uses 26 PCICLK/xfer regardles of PIO mode */ /* * VIA SouthBridge chips. @@ -101,11 +100,9 @@ unsigned char rev_max; unsigned short flags; } via_isa_bridges[] = { -#ifdef VIA_NEW_BRIDGES_TESTED { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, - { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_66 }, -#endif - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 | VIA_BAD_PIO }, + { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, + { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, @@ -154,7 +151,7 @@ via_print("----------VIA BusMastering IDE Configuration----------------"); - via_print("Driver Version: 3.23"); + via_print("Driver Version: 3.26"); via_print("South Bridge: VIA %s", via_config->name); pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); @@ -220,8 +217,8 @@ switch (via_config->flags & VIA_UDMA) { case VIA_UDMA_100: - speed[i] = 2000 / udma[i]; - cycle[i] = 10 * udma[i]; + speed[i] = 60 * via_clock / udma[i]; + cycle[i] = 333 / via_clock * udma[i]; break; case VIA_UDMA_66: @@ -301,7 +298,7 @@ switch (via_config->flags & VIA_UDMA) { case VIA_UDMA_33: UT = T; break; case VIA_UDMA_66: UT = T/2; break; - case VIA_UDMA_100: UT = 10; break; + case VIA_UDMA_100: UT = T/3; break; default: UT = T; break; } diff -u --recursive --new-file v2.4.9/linux/drivers/md/lvm.c linux/drivers/md/lvm.c --- v2.4.9/linux/drivers/md/lvm.c Wed Jul 25 17:10:20 2001 +++ linux/drivers/md/lvm.c Mon Aug 27 14:20:21 2001 @@ -1059,7 +1059,6 @@ lvm_name, minor, VG_BLK(minor), LV_BLK(minor)); #endif - sync_dev(inode->i_rdev); if (lv_ptr->lv_open == 1) vg_ptr->lv_open--; lv_ptr->lv_open--; diff -u --recursive --new-file v2.4.9/linux/drivers/media/video/videodev.c linux/drivers/media/video/videodev.c --- v2.4.9/linux/drivers/media/video/videodev.c Mon Aug 27 12:41:42 2001 +++ linux/drivers/media/video/videodev.c Tue Aug 28 07:00:58 2001 @@ -164,7 +164,6 @@ if(vfl->owner) __MOD_INC_USE_COUNT(vfl->owner); - unlock_kernel(); if(vfl->open) { @@ -175,9 +174,11 @@ if(vfl->owner) __MOD_DEC_USE_COUNT(vfl->owner); + unlock_kernel(); return err; } } + unlock_kernel(); return 0; error_out: unlock_kernel(); diff -u --recursive --new-file v2.4.9/linux/drivers/net/wireless/airport.c linux/drivers/net/wireless/airport.c --- v2.4.9/linux/drivers/net/wireless/airport.c Mon Aug 27 12:41:43 2001 +++ linux/drivers/net/wireless/airport.c Mon Aug 27 09:00:37 2001 @@ -5,6 +5,10 @@ * * Copyright notice & release notes in file orinoco.c * + * Note specific to airport stub: + * + * 0.05 : first version of the new split driver + * 0.06 : fix possible hang on powerup, add sleep support */ #include @@ -25,9 +29,12 @@ #include #include #include +#include +#include #include #include +#include #include "hermes.h" #include "orinoco.h" @@ -40,10 +47,18 @@ struct device_node* node; int irq_requested; int ndev_registered; + int open; /* Common structure (fully included), see orinoco.h */ struct dldwd_priv priv; } dldwd_card_t; +#ifdef CONFIG_PMAC_PBOOK +static int airport_sleep_notify(struct pmu_sleep_notifier *self, int when); +static struct pmu_sleep_notifier airport_sleep_notifier = { + airport_sleep_notify, SLEEP_LEVEL_NET, +}; +#endif + /* * Function prototypes */ @@ -69,24 +84,15 @@ static int airport_init(struct net_device *dev) { dldwd_priv_t *priv = dev->priv; - dldwd_card_t* card = (dldwd_card_t *)priv->card; int rc; TRACE_ENTER(priv->ndev.name); MOD_INC_USE_COUNT; - feature_set_airport_power(card->node, 1); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); - rc = dldwd_init(dev); - if (rc) { - feature_set_airport_power(card->node, 0); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ); - } - priv->hw_ready = 1; + if (!rc) + priv->hw_ready = 1; MOD_DEC_USE_COUNT; @@ -97,18 +103,20 @@ airport_open(struct net_device *dev) { dldwd_priv_t *priv = dev->priv; + dldwd_card_t* card = (dldwd_card_t *)priv->card; int rc; TRACE_ENTER(priv->ndev.name); - netif_device_attach(dev); rc = dldwd_reset(priv); if (rc) airport_stop(dev); - else - netif_start_queue(dev); + else { + card->open = 1; + netif_device_attach(dev); + } - TRACE_EXIT(priv->ndev.name); +// TRACE_EXIT(priv->ndev.name); return rc; } @@ -117,18 +125,66 @@ airport_stop(struct net_device *dev) { dldwd_priv_t *priv = dev->priv; + dldwd_card_t* card = (dldwd_card_t *)priv->card; TRACE_ENTER(priv->ndev.name); netif_stop_queue(dev); - dldwd_shutdown(priv); + card->open = 0; TRACE_EXIT(priv->ndev.name); return 0; } +#ifdef CONFIG_PMAC_PBOOK +static int +airport_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + dldwd_priv_t *priv; + struct net_device *ndev; + dldwd_card_t* card; + int rc; + + if (!airport_dev) + return PBOOK_SLEEP_OK; + priv = airport_dev; + ndev = &priv->ndev; + card = (dldwd_card_t *)priv->card; + + switch (when) { + case PBOOK_SLEEP_REQUEST: + break; + case PBOOK_SLEEP_REJECT: + break; + case PBOOK_SLEEP_NOW: + printk(KERN_INFO "%s: Airport entering sleep mode\n", ndev->name); + netif_device_detach(ndev); + if (card->open) + dldwd_shutdown(priv); + disable_irq(ndev->irq); + feature_set_airport_power(card->node, 0); + priv->hw_ready = 0; + break; + case PBOOK_WAKE: + printk(KERN_INFO "%s: Airport waking up\n", ndev->name); + feature_set_airport_power(card->node, 1); + mdelay(200); + hermes_reset(&priv->hw); + priv->hw_ready = 1; + rc = dldwd_reset(priv); + if (rc) + printk(KERN_ERR "airport: Error %d re-initing card !\n", rc); + else if (card->open) + netif_device_attach(ndev); + enable_irq(ndev->irq); + break; + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ + static dldwd_priv_t* airport_attach(struct device_node* of_node) { @@ -175,6 +231,14 @@ hermes_struct_init(hw, ndev->base_addr); + /* Power up card */ + feature_set_airport_power(card->node, 1); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); + + /* Reset it before we get the interrupt */ + hermes_reset(hw); + if (request_irq(ndev->irq, dldwd_interrupt, 0, "Airport", (void *)priv)) { printk(KERN_ERR "airport: Couldn't get IRQ %d\n", ndev->irq); goto failed; @@ -198,6 +262,9 @@ printk(KERN_ERR "airport: Failed to create /proc node for %s\n", ndev->name); +#ifdef CONFIG_PMAC_PBOOK + pmu_register_sleep_notifier(&airport_sleep_notifier); +#endif return priv; failed: @@ -219,6 +286,9 @@ /* Unregister proc entry */ dldwd_proc_dev_cleanup(priv); +#ifdef CONFIG_PMAC_PBOOK + pmu_unregister_sleep_notifier(&airport_sleep_notifier); +#endif if (card->ndev_registered) unregister_netdev(&priv->ndev); card->ndev_registered = 0; @@ -265,8 +335,6 @@ airport_detach(airport_dev); airport_dev = NULL; } - -MODULE_DESCRIPTION("Apple Airport driver"); module_init(init_airport); module_exit(exit_airport); diff -u --recursive --new-file v2.4.9/linux/drivers/pci/names.c linux/drivers/pci/names.c --- v2.4.9/linux/drivers/pci/names.c Mon Oct 2 12:00:16 2000 +++ linux/drivers/pci/names.c Mon Aug 27 08:47:07 2001 @@ -32,9 +32,9 @@ * real memory.. Parse the same file multiple times * to get all the info. */ -#define VENDOR( vendor, name ) static const char __vendorstr_##vendor[] __initdata = name; +#define VENDOR( vendor, name ) static char __vendorstr_##vendor[] __initdata = name; #define ENDVENDOR() -#define DEVICE( vendor, device, name ) static const char __devicestr_##vendor##device[] __initdata = name; +#define DEVICE( vendor, device, name ) static char __devicestr_##vendor##device[] __initdata = name; #include "devlist.h" @@ -43,7 +43,7 @@ #define DEVICE( vendor, device, name ) { 0x##device, 0, __devicestr_##vendor##device }, #include "devlist.h" -static const struct pci_vendor_info __initdata pci_vendor_list[] = { +static struct pci_vendor_info __initdata pci_vendor_list[] = { #define VENDOR( vendor, name ) { 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor }, #define ENDVENDOR() #define DEVICE( vendor, device, name ) diff -u --recursive --new-file v2.4.9/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.4.9/linux/drivers/pcmcia/yenta.c Wed Jul 25 17:10:22 2001 +++ linux/drivers/pcmcia/yenta.c Mon Aug 27 08:05:50 2001 @@ -729,7 +729,7 @@ if (type & IORESOURCE_IO) { align = 1024; size = 256; - min = PCIBIOS_MIN_IO; + min = 0x4000; max = 0xffff; } diff -u --recursive --new-file v2.4.9/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c --- v2.4.9/linux/drivers/s390/block/dasd.c Sun Aug 12 13:27:59 2001 +++ linux/drivers/s390/block/dasd.c Mon Aug 27 14:20:21 2001 @@ -2140,13 +2140,7 @@ } for (i = (1 << DASD_PARTN_BITS) - 1; i >= 0; i--) { int major = device->major_info->gendisk.major; - int minor = start + i; - kdev_t devi = MKDEV (major, minor); - struct super_block *sb = get_super (devi); - sync_dev (devi); - if (sb) - invalidate_inodes (sb); - invalidate_buffers (devi); + invalidate_device(MKDEV (major, start+i), 1); } dasd_destroy_partitions(device); dasd_setup_partitions(device); @@ -2517,7 +2511,6 @@ rc = -ENODEV; goto out; } - fsync_dev (inp->i_rdev); /* sync the device */ count = atomic_dec_return (&device->open_count); if ( count == 0) { invalidate_buffers (inp->i_rdev); diff -u --recursive --new-file v2.4.9/linux/drivers/s390/block/xpram.c linux/drivers/s390/block/xpram.c --- v2.4.9/linux/drivers/s390/block/xpram.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/s390/block/xpram.c Mon Aug 27 14:20:21 2001 @@ -625,8 +625,7 @@ */ if (!atomic_dec_return(&(dev->usage))) { /* but flush it right now */ - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); + /* Everything is already flushed by caller -- AV */ } MOD_DEC_USE_COUNT; return(0); diff -u --recursive --new-file v2.4.9/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.4.9/linux/drivers/sbus/char/pcikbd.c Mon Aug 27 12:41:44 2001 +++ linux/drivers/sbus/char/pcikbd.c Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.59 2001/08/13 14:40:08 davem Exp $ +/* $Id: pcikbd.c,v 1.61 2001/08/18 09:40:46 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,17 @@ "\r\000/"; /* 0x60 - 0x6f */ #endif +#define DEFAULT_KEYB_REP_DELAY 250 +#define DEFAULT_KEYB_REP_RATE 30 /* cps */ + +static struct kbd_repeat kbdrate = { + DEFAULT_KEYB_REP_DELAY, + DEFAULT_KEYB_REP_RATE +}; + +static unsigned char parse_kbd_rate(struct kbd_repeat *r); +static int write_kbd_rate(unsigned char r); + int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode) { if(scancode < SC_LIM || scancode > 255 || keycode > 127) @@ -335,12 +347,7 @@ printk("Prom Leave: Enable Keyboard: no ACK\n"); /* Reset keyboard rate */ - pcikbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - printk("Prom Leave: Set rate: no ACK\n"); - pcikbd_write(KBD_DATA_REG, 0x00); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - printk("Prom Leave: Set rate: no ACK\n"); + write_kbd_rate(parse_kbd_rate(&kbdrate)); } int pcikbd_translate(unsigned char scancode, unsigned char *keycode, @@ -478,8 +485,81 @@ send_data(KBD_CMD_ENABLE); } -int pcikbd_rate(struct kbd_repeat *rep) +static unsigned char parse_kbd_rate(struct kbd_repeat *r) +{ + static struct r2v { + int rate; + unsigned char val; + } kbd_rates[]={ { 5, 0x14 }, + { 7, 0x10 }, + { 10, 0x0c }, + { 15, 0x08 }, + { 20, 0x04 }, + { 25, 0x02 }, + { 30, 0x00 } }; + static struct d2v { + int delay; + unsigned char val; + } kbd_delays[]={ { 250, 0 }, + { 500, 1 }, + { 750, 2 }, + { 1000, 3 } }; + int rate = 0, delay = 0; + + if (r != NULL) { + int i, new_rate = 30, new_delay = 250; + if (r->rate <= 0) + r->rate = kbdrate.rate; + if (r->delay <= 0) + r->delay = kbdrate.delay; + + for (i = 0; i < sizeof(kbd_rates) / sizeof(struct r2v); i++) { + if (kbd_rates[i].rate == r->rate) { + new_rate = kbd_rates[i].rate; + rate = kbd_rates[i].val; + break; + } + } + for (i=0; i < sizeof(kbd_delays) / sizeof(struct d2v); i++) { + if (kbd_delays[i].delay == r->delay) { + new_delay = kbd_delays[i].delay; + delay = kbd_delays[i].val; + break; + } + } + r->rate = new_rate; + r->delay = new_delay; + } + return (delay << 5) | rate; +} + +static int write_kbd_rate(unsigned char r) +{ + if (!send_data(KBD_CMD_SET_RATE) || !send_data(r)) { + /* re-enable kbd if any errors */ + send_data(KBD_CMD_ENABLE); + return 0; + } + + return 1; +} + +static int pcikbd_rate(struct kbd_repeat *rep) { + unsigned char r; + struct kbd_repeat old_rep; + + if (rep == NULL) + return -EINVAL; + + r = parse_kbd_rate(rep); + memcpy(&old_rep, &kbdrate, sizeof(struct kbd_repeat)); + if (write_kbd_rate(r)) { + memcpy(&kbdrate,rep,sizeof(struct kbd_repeat)); + memcpy(rep,&old_rep,sizeof(struct kbd_repeat)); + return 0; + } + return -EIO; } @@ -641,12 +721,7 @@ if(pcikbd_wait_for_input() != KBD_REPLY_ACK) return "Enable keyboard: no ACK"; - pcikbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; - pcikbd_write(KBD_DATA_REG, 0x00); - if(pcikbd_wait_for_input() != KBD_REPLY_ACK) - return "Set rate: no ACK"; + write_kbd_rate(parse_kbd_rate(&kbdrate)); return NULL; /* success */ } @@ -744,6 +819,7 @@ } kd_mksound = nop_kd_mksound; + kbd_rate = pcikbd_rate; #ifdef __sparc_v9__ edev = 0; diff -u --recursive --new-file v2.4.9/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.4.9/linux/drivers/scsi/sr.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/scsi/sr.c Mon Aug 27 14:20:21 2001 @@ -101,7 +101,6 @@ { if (scsi_CDs[MINOR(cdi->dev)].device->sector_size > 2048) sr_set_blocklength(MINOR(cdi->dev), 2048); - sync_dev(cdi->dev); scsi_CDs[MINOR(cdi->dev)].device->access_count--; if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module) __MOD_DEC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c --- v2.4.9/linux/drivers/sgi/char/ds1286.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/sgi/char/ds1286.c Mon Aug 27 08:56:31 2001 @@ -1,32 +1,30 @@ -/* $Id: ds1286.c,v 1.6 1999/10/09 00:01:31 ralf Exp $ - * - * Real Time Clock interface for Linux +/* + * DS1286 Real Time Clock interface for Linux * - * Copyright (C) 1998, 1999 Ralf Baechle + * Copyright (C) 1998, 1999, 2000 Ralf Baechle * - * Based on code written by Paul Gortmaker. + * Based on code written by Paul Gortmaker. * - * This driver allows use of the real time clock (built into - * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/rtc - * pseudo-file for status information. + * This driver allows use of the real time clock (built into nearly all + * computers) from user space. It exports the /dev/rtc interface supporting + * various ioctl() and also the /proc/rtc pseudo-file for status + * information. * - * The ioctls can be used to set the interrupt behaviour and - * generation rate from the RTC via IRQ 8. Then the /dev/rtc - * interface can be used to make use of these timer interrupts, - * be they interval or alarm based. + * The ioctls can be used to set the interrupt behaviour and generation rate + * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make + * use of these timer interrupts, be they interval or alarm based. * - * The /dev/rtc interface will block on reads until an interrupt - * has been received. If a RTC interrupt has already happened, - * it will output an unsigned long and then block. The output value - * contains the interrupt status in the low byte and the number of - * interrupts since the last read in the remaining high bytes. The - * /dev/rtc interface can also be used with the select(2) call. + * The /dev/rtc interface will block on reads until an interrupt has been + * received. If a RTC interrupt has already happened, it will output an + * unsigned long and then block. The output value contains the interrupt + * status in the low byte and the number of interrupts since the last read + * in the remaining high bytes. The /dev/rtc interface can also be used with + * the select(2) call. * - * 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 free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. */ #include #include @@ -38,7 +36,6 @@ #include #include #include -#include #include #include @@ -81,58 +78,20 @@ #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ #define RTC_TIMER_ON 0x02 /* missed irq timer active */ -unsigned char ds1286_status = 0; /* bitmapped status byte. */ -unsigned long ds1286_freq = 0; /* Current periodic IRQ rate */ -unsigned long ds1286_irq_data = 0; /* our output to the world */ +unsigned char ds1286_status; /* bitmapped status byte. */ +unsigned long ds1286_freq; /* Current periodic IRQ rate */ unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* - * A very tiny interrupt handler. It runs with SA_INTERRUPT set, - * so that there is no possibility of conflicting with the - * set_rtc_mmss() call that happens during some timer interrupts. - * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) - */ - -/* * Now all the various file operations that we export. */ static ssize_t ds1286_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); - unsigned long data; - ssize_t retval; - - if (count < sizeof(unsigned long)) - return -EINVAL; - - add_wait_queue(&ds1286_wait, &wait); - - current->state = TASK_INTERRUPTIBLE; - - while ((data = xchg(&ds1286_irq_data, 0)) == 0) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto out; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - goto out; - } - schedule(); - } - - retval = put_user(data, (unsigned long *)buf); - if (!retval) - retval = sizeof(unsigned long); - out: - current->state = TASK_RUNNING; - remove_wait_queue(&ds1286_wait, &wait); - - return retval; + return -EIO; } static int ds1286_ioctl(struct inode *inode, struct file *file, @@ -338,27 +297,32 @@ static int ds1286_open(struct inode *inode, struct file *file) { - if(ds1286_status & RTC_IS_OPEN) - return -EBUSY; + spin_lock_irq(&ds1286_lock); + + if (ds1286_status & RTC_IS_OPEN) + goto out_busy; ds1286_status |= RTC_IS_OPEN; - ds1286_irq_data = 0; + + spin_lock_irq(&ds1286_lock); return 0; + +out_busy: + spin_lock_irq(&ds1286_lock); + return -EBUSY; } static int ds1286_release(struct inode *inode, struct file *file) { - lock_kernel(); ds1286_status &= ~RTC_IS_OPEN; - unlock_kernel(); + return 0; } static unsigned int ds1286_poll(struct file *file, poll_table *wait) { poll_wait(file, &ds1286_wait, wait); - if (ds1286_irq_data != 0) - return POLLIN | POLLRDNORM; + return 0; } @@ -407,7 +371,7 @@ get_rtc_time(&tm); hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND); - hundredth = BCD_TO_BIN(hundredth); + BCD_TO_BIN(hundredth); p += sprintf(p, "rtc_time\t: %02d:%02d:%02d.%02d\n" diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c --- v2.4.9/linux/drivers/sgi/char/graphics.c Mon Mar 19 12:35:09 2001 +++ linux/drivers/sgi/char/graphics.c Mon Aug 27 08:56:31 2001 @@ -1,5 +1,4 @@ -/* $Id: graphics.c,v 1.22 2000/02/18 00:24:43 ralf Exp $ - * +/* * gfx.c: support for SGI's /dev/graphics, /dev/opengl * * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -214,8 +213,7 @@ /* * This is the core of the direct rendering engine. */ - -unsigned long +struct page * sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int no_share) { @@ -250,7 +248,6 @@ pgd = pgd_offset(current->mm, address); pmd = pmd_offset(pgd, address); pte = pte_offset(pmd, address); - printk("page: %08lx\n", pte_page(*pte)); return pte_page(*pte); } diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/graphics_syms.c linux/drivers/sgi/char/graphics_syms.c --- v2.4.9/linux/drivers/sgi/char/graphics_syms.c Mon Feb 28 07:18:20 2000 +++ linux/drivers/sgi/char/graphics_syms.c Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * graphics_syms.c: interfaces for SGI Indy newport graphics - * - * Copyright (C) 1999 Alex deVries - * - * We should not even be trying to compile this if we are not doing - * a module. - */ - -#define __NO_VERSION__ -#include - -/* extern int rrm_command (unsigned int cmd, void *arg); -extern int rrm_close (struct inode *inode, struct file *file); -EXPORT_SYMBOL(rrm_command); -EXPORT_SYMBOL(rrm_close); - - -*/ -extern void shmiq_init (void); -extern void usema_init(void); - -EXPORT_SYMBOL(shmiq_init); -EXPORT_SYMBOL(usema_init); - -extern void disable_gconsole(void); -extern void enable_gconsole(void); -extern void remove_mapping (struct task_struct *task, unsigned long start, - unsigned long end); - -EXPORT_SYMBOL(disable_gconsole); -EXPORT_SYMBOL(enable_gconsole); -EXPORT_SYMBOL(remove_mapping); - -EXPORT_SYMBOL(npregs); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/newport.c linux/drivers/sgi/char/newport.c --- v2.4.9/linux/drivers/sgi/char/newport.c Mon Feb 28 07:18:20 2000 +++ linux/drivers/sgi/char/newport.c Mon Aug 27 08:56:31 2001 @@ -16,6 +16,8 @@ struct newport_regs *npregs; +EXPORT_SYMBOL(npregs); + /* Kernel routines for supporting graphics context switching */ void newport_save (void *y) diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/rrm.c linux/drivers/sgi/char/rrm.c --- v2.4.9/linux/drivers/sgi/char/rrm.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sgi/char/rrm.c Mon Aug 27 08:56:31 2001 @@ -9,12 +9,11 @@ * * Fixes: */ +#include + #include #include -#ifdef MODULE -#include -#endif int rrm_open_rn (int rnid, void *arg) @@ -71,3 +70,6 @@ /* This routine is invoked when the device is closed */ return 0; } + +EXPORT_SYMBOL(rrm_command); +EXPORT_SYMBOL(rrm_close); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/sgicons.c linux/drivers/sgi/char/sgicons.c --- v2.4.9/linux/drivers/sgi/char/sgicons.c Sun Jul 9 22:32:58 2000 +++ linux/drivers/sgi/char/sgicons.c Mon Aug 27 08:56:31 2001 @@ -1,5 +1,4 @@ -/* $Id: sgicons.c,v 1.10 1998/08/25 09:18:58 ralf Exp $ - * +/* * sgicons.c: Setting up and registering console I/O on the SGI. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -10,12 +9,10 @@ #include #include #include +#include #include #include "gconsole.h" -/* To make psaux code cleaner */ -unsigned char aux_device_present = 0xaa; - /* This is the system graphics console (the first adapter found) */ struct console_ops *gconsole = 0; struct console_ops *real_gconsole = 0; @@ -35,6 +32,9 @@ gconsole = 0; } } + +EXPORT_SYMBOL(disable_gconsole); +EXPORT_SYMBOL(enable_gconsole); void register_gconsole (struct console_ops *gc) diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c --- v2.4.9/linux/drivers/sgi/char/sgiserial.c Thu Oct 12 14:20:47 2000 +++ linux/drivers/sgi/char/sgiserial.c Mon Aug 27 08:56:31 2001 @@ -13,6 +13,9 @@ * thorough pass to merge in the rest of the updates. * Better still, someone really ought to make it a common * code module for both platforms. kevink@mips.com + * + * 20010616 - Klaus Naumann : Make serial console work with + * any speed - not only 9600 */ #include /* for CONFIG_REMOTE_DEBUG */ @@ -58,9 +61,9 @@ static int zilog_irq = SGI_SERIAL_IRQ; /* Console hooks... */ -static int zs_cons_chanout = 0; -static int zs_cons_chanin = 0; -struct sgi_serial *zs_consinfo = 0; +static int zs_cons_chanout; +static int zs_cons_chanin; +struct sgi_serial *zs_consinfo; static unsigned char kgdb_regs[16] = { 0, 0, 0, /* write 0, 1, 2 */ @@ -97,6 +100,7 @@ DECLARE_TASK_QUEUE(tq_serial); struct tty_driver serial_driver, callout_driver; +struct console *sgisercon; static int serial_refcount; /* serial subtype definitions */ @@ -144,10 +148,10 @@ dev_t device, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = + static const char *badmagic = KERN_WARNING "Warning: bad magic number for serial struct (%d, %d) in %s\n"; - static const char *badinfo = - "Warning: null sun_serial for (%d, %d) in %s\n"; + static const char *badinfo = KERN_WARNING + "Warning: null sgi_serial for (%d, %d) in %s\n"; if (!info) { printk(badinfo, MAJOR(device), MINOR(device), routine); @@ -178,7 +182,8 @@ * interrupts are enabled. Therefore we have to check ioc_iocontrol before we * access it. */ -static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg) +static inline unsigned char read_zsreg(struct sgi_zschannel *channel, + unsigned char reg) { unsigned char retval; volatile unsigned char junk; @@ -192,7 +197,8 @@ return retval; } -static inline void write_zsreg(struct sgi_zschannel *channel, unsigned char reg, unsigned char value) +static inline void write_zsreg(struct sgi_zschannel *channel, + unsigned char reg, unsigned char value) { volatile unsigned char junk; @@ -323,7 +329,7 @@ */ static void batten_down_hatches(void) { - prom_imode(); + ArcEnterInteractiveMode(); #if 0 /* If we are doing kadb, we call the debugger * else we just drop into the boot monitor. @@ -682,7 +688,7 @@ save_flags(flags); cli(); #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttys%d (irq %d)...", info->line, info->irq); + printk("starting up ttys%d (irq %d)...\n", info->line, info->irq); #endif /* @@ -1302,6 +1308,59 @@ junk = ioc_icontrol->istat0; sti(); return put_user(status,value); +} + +static int get_modem_info(struct sgi_serial * info, unsigned int *value) +{ + unsigned char status; + unsigned int result; + + cli(); + status = info->zs_channel->control; + udelay(2); + sti(); + result = ((info->curregs[5] & RTS) ? TIOCM_RTS : 0) + | ((info->curregs[5] & DTR) ? TIOCM_DTR : 0) + | ((status & DCD) ? TIOCM_CAR : 0) + | ((status & SYNC) ? TIOCM_DSR : 0) + | ((status & CTS) ? TIOCM_CTS : 0); + if (put_user(result, value)) + return -EFAULT; + return 0; +} + +static int set_modem_info(struct sgi_serial * info, unsigned int cmd, + unsigned int *value) +{ + unsigned int arg; + + if (get_user(arg, value)) + return -EFAULT; + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + info->curregs[5] |= RTS; + if (arg & TIOCM_DTR) + info->curregs[5] |= DTR; + break; + case TIOCMBIC: + if (arg & TIOCM_RTS) + info->curregs[5] &= ~RTS; + if (arg & TIOCM_DTR) + info->curregs[5] &= ~DTR; + break; + case TIOCMSET: + info->curregs[5] = ((info->curregs[5] & ~(RTS | DTR)) + | ((arg & TIOCM_RTS) ? RTS : 0) + | ((arg & TIOCM_DTR) ? DTR : 0)); + break; + default: + return -EINVAL; + } + cli(); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + sti(); + return 0; } /* @@ -1322,11 +1381,10 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int error; - struct sgi_serial * info = (struct sgi_serial *)tty->driver_data; + struct sgi_serial * info = (struct sgi_serial *) tty->driver_data; int retval; - if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + if (serial_paranoia_check(info, tty->device, "zs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && @@ -1353,45 +1411,36 @@ send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: - error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); - if (error) - return error; - put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg); + if (put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg)) + return -EFAULT; return 0; case TIOCSSOFTCAR: - error = get_user(arg, (unsigned long *)arg); - if (error) - return error; + if (get_user(arg, (unsigned long *) arg)) + return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct)); - if (error) - return error; return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - else - return get_lsr_info(info, (unsigned int *) arg); + return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct sgi_serial)); - if (error) - return error; - copy_to_user((struct sun_serial *) arg, - info, sizeof(struct sgi_serial)); + if (copy_to_user((struct sgi_serial *) arg, + info, sizeof(struct sgi_serial))) + return -EFAULT; return 0; default: @@ -1727,11 +1776,19 @@ change_speed(info); } + /* If this is the serial console change the speed to + * the right value + */ + if (info->is_cons) { + info->tty->termios->c_cflag = sgisercon->cflag; + change_speed(info); + } + info->session = current->session; info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttys%d successful...", info->line); + printk("rs_open ttys%d successful...\n", info->line); #endif return 0; } @@ -1748,13 +1805,10 @@ { extern struct hpc3_miscregs *hpc3mregs; - if(chip > 0) { - prom_printf("Wheee, bogus zs chip number requested.\n"); - prom_getchar(); - romvec->imode(); - } - return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd); + if (chip > 0) + panic("Wheee, bogus zs chip number requested."); + return (struct sgi_zslayout *) (&hpc3mregs->ser1cmd); } @@ -1784,13 +1838,6 @@ } if(o && i) io = 1; - if(ss->zs_baud != 9562) { /* Don't ask... */ - prom_printf("BAD console baud rate %d\n", ss->zs_baud); - prom_getchar(); - prom_imode(); - panic("Console baud rate weirdness"); - } - /* Set flag variable for this port so that it cannot be * opened for other uses by accident. @@ -1798,7 +1845,7 @@ ss->is_cons = 1; if(io) { - if(!msg_printed) { + if (!msg_printed) { printk("zs%d: console I/O\n", ((channel>>1)&1)); msg_printed = 1; } @@ -1806,7 +1853,6 @@ } else { printk("zs%d: console %s\n", ((channel>>1)&1), (i==1 ? "input" : (o==1 ? "output" : "WEIRD"))); - } } @@ -2002,7 +2048,6 @@ rs_cons_hook(int chip, int out, int line) { int channel; - if(chip) panic("rs_cons_hook called with chip not zero"); @@ -2087,11 +2132,11 @@ static int __init zs_console_setup(struct console *con, char *options) { struct sgi_serial *info; - int baud = 9600; + int baud; int bits = 8; int parity = 'n'; int cflag = CREAD | HUPCL | CLOCAL; - char *s; + char *s, *dbaud; int i, brg; if (options) { @@ -2102,6 +2147,21 @@ if (*s) parity = *s++; if (*s) bits = *s - '0'; } + else { + /* If the user doesn't set console=... try to read the + * PROM variable - if this fails use 9600 baud and + * inform the user about the problem + */ + dbaud = ArcGetEnvironmentVariable("dbaud"); + if(dbaud) baud = simple_strtoul(dbaud, NULL, 10); + else { + /* Use prom_printf() to make sure that the user + * is getting anything ... + */ + prom_printf("No dbaud set in PROM ?!? Using 9600.\n"); + baud = 9600; + } + } /* * Now construct a cflag setting. @@ -2156,7 +2216,8 @@ info = zs_soft + con->index; info->is_cons = 1; - printk("Console: ttyS%d (Zilog8530)\n", info->line); + printk("Console: ttyS%d (Zilog8530), %d baud\n", + info->line, baud); i = con->cflag & CBAUD; if (con->cflag & CBAUDEX) { @@ -2195,6 +2256,8 @@ zscons_regs[4] |= SB2; else zscons_regs[4] |= SB1; + + sgisercon = con; brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor); zscons_regs[12] = brg & 0xff; diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/sgiserial.h linux/drivers/sgi/char/sgiserial.h --- v2.4.9/linux/drivers/sgi/char/sgiserial.h Fri Jun 25 17:39:34 1999 +++ linux/drivers/sgi/char/sgiserial.h Mon Aug 27 08:56:31 2001 @@ -359,7 +359,7 @@ #define ZCOUNT 0x2 /* Zero count */ #define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ #define DCD 0x8 /* DCD */ -#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define SYNC 0x10 /* Sync/hunt */ #define CTS 0x20 /* CTS */ #define TxEOM 0x40 /* Tx underrun */ #define BRK_ABRT 0x80 /* Break/Abort */ diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c --- v2.4.9/linux/drivers/sgi/char/shmiq.c Mon Mar 19 12:35:09 2001 +++ linux/drivers/sgi/char/shmiq.c Mon Aug 27 08:56:31 2001 @@ -1,5 +1,4 @@ -/* $Id: shmiq.c,v 1.19 2000/02/23 00:41:21 ralf Exp $ - * +/* * shmiq.c: shared memory input queue driver * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -42,7 +41,6 @@ * Until then, I just allow for 1 qcntl device. * */ - #include #include #include @@ -52,6 +50,7 @@ #include #include #include +#include #include #include @@ -470,3 +469,5 @@ S_IFCHR | S_IRUSR | S_IWUSR, &shmiq_fops, NULL); } + +EXPORT_SYMBOL(shmiq_init); diff -u --recursive --new-file v2.4.9/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c --- v2.4.9/linux/drivers/sgi/char/usema.c Wed Jul 12 21:58:43 2000 +++ linux/drivers/sgi/char/usema.c Mon Aug 27 08:56:31 2001 @@ -20,8 +20,7 @@ * usema(7m), usinit(3p), usnewsema(3p) * /usr/include/sys/usioctl.h * -*/ - + */ #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include #include #include #include "usema.h" @@ -180,3 +180,5 @@ SGI_USEMACLONE); misc_register(&dev_usemaclone); } + +EXPORT_SYMBOL(usema_init); diff -u --recursive --new-file v2.4.9/linux/drivers/sound/awe_wave.c linux/drivers/sound/awe_wave.c --- v2.4.9/linux/drivers/sound/awe_wave.c Fri Mar 2 11:12:11 2001 +++ linux/drivers/sound/awe_wave.c Mon Aug 27 08:11:43 2001 @@ -4873,7 +4873,7 @@ /* any three numbers you like */ #define UNIQUE_ID1 0x1234 #define UNIQUE_ID2 0x4321 -#define UNIQUE_ID3 0xFFFF +#define UNIQUE_ID3 0xABCD static void __init awe_check_dram(void) diff -u --recursive --new-file v2.4.9/linux/drivers/tc/lk201-map.map linux/drivers/tc/lk201-map.map --- v2.4.9/linux/drivers/tc/lk201-map.map Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/lk201-map.map Mon Aug 27 08:56:31 2001 @@ -0,0 +1,356 @@ +# Default kernel keymap. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,12 +# Change the above line into +# keymaps 0-2,4-6,8,12 +# in case you want the entries +# altgr control keycode 83 = Boot +# altgr control keycode 111 = Boot +# below. +# +# In fact AltGr is used very little, and one more keymap can +# be saved by mapping AltGr to Alt (and adapting a few entries): +# keycode 100 = Alt +# +keycode 0x15 = grave tilde + alt keycode 0x15 = Escape + control keycode 0x15 = Meta_Escape +keycode 0x16 = one exclam + alt keycode 0x16 = Meta_one +keycode 0x17 = two at at + control keycode 0x17 = nul + shift control keycode 0x17 = nul + alt keycode 0x17 = Meta_two +keycode 0x18 = three numbersign + control keycode 0x18 = Escape + alt keycode 0x18 = Meta_three +keycode 0x19 = four dollar dollar + control keycode 0x19 = Control_backslash + alt keycode 0x19 = Meta_four +keycode 0x1a = five percent + control keycode 0x1a = Control_bracketright + alt keycode 0x1a = Meta_five +keycode 0x1b = six asciicircum + control keycode 0x1b = Control_asciicircum + alt keycode 0x1b = Meta_six +keycode 0x1c = seven ampersand braceleft + control keycode 0x1c = Control_underscore + alt keycode 0x1c = Meta_seven +keycode 0x1d = eight asterisk bracketleft + control keycode 0x1d = Delete + alt keycode 0x1d = Meta_eight +keycode 0x1e = nine parenleft bracketright + alt keycode 0x1e = Meta_nine +keycode 0x1f = zero parenright braceright + alt keycode 0x1f = Meta_zero +keycode 0x20 = minus underscore backslash + control keycode 0x20 = Control_underscore + shift control keycode 0x20 = Control_underscore + alt keycode 0x20 = Meta_minus +keycode 0x21 = equal plus + alt keycode 0x21 = Meta_equal +keycode 0x22 = Delete Delete + control keycode 0x22 = BackSpace + alt keycode 0x22 = Meta_Delete +keycode 0x2a = Tab Tab + alt keycode 0x2a = Meta_Tab +keycode 0x2b = q +keycode 0x2c = w +keycode 0x2d = e + altgr keycode 0x2d = Hex_E +keycode 0x2e = r +keycode 0x2f = t +keycode 0x30 = y +keycode 0x31 = u +keycode 0x32 = i +keycode 0x33 = o +keycode 0x34 = p +keycode 0x35 = bracketleft braceleft + control keycode 0x35 = Escape + alt keycode 0x35 = Meta_bracketleft +keycode 0x36 = bracketright braceright asciitilde + control keycode 0x36 = Control_bracketright + alt keycode 0x36 = Meta_bracketright +keycode 0x37 = Return + alt keycode 0x37 = Meta_Control_m +keycode 0x3f = Control +keycode 0x41 = a + altgr keycode 0x41 = Hex_A +keycode 0x42 = s +keycode 0x43 = d + altgr keycode 0x43 = Hex_D +keycode 0x44 = f + altgr keycode 0x44 = Hex_F +keycode 0x45 = g +keycode 0x46 = h +keycode 0x47 = j +keycode 0x48 = k +keycode 0x49 = l +keycode 0x4a = semicolon colon + alt keycode 0x4a = Meta_semicolon +keycode 0x4b = apostrophe quotedbl + control keycode 0x4b = Control_g + alt keycode 0x4b = Meta_apostrophe +# keycode 41 = grave asciitilde +# control keycode 41 = nul +# alt keycode 41 = Meta_grave +keycode 0x52 = Shift +keycode 0x4c = backslash bar + control keycode 0x4c = Control_backslash + alt keycode 0x4c = Meta_backslash +keycode 0x53 = greater less +keycode 0x54 = z +keycode 0x55 = x +keycode 0x56 = c + altgr keycode 0x56 = Hex_C +keycode 0x57 = v +keycode 0x58 = b + altgr keycode 0x58 = Hex_B +keycode 0x59 = n +keycode 0x5a = m +keycode 0x5b = comma less + alt keycode 0x5b = Meta_comma +keycode 0x5c = period greater + control keycode 0x5c = Compose + alt keycode 0x5c = Meta_period +keycode 0x5d = slash question + control keycode 0x5d = Delete + alt keycode 0x5d = Meta_slash + +keycode 0x67 = Alt +keycode 0x68 = space space + control keycode 0x68 = nul + alt keycode 0x68 = Meta_space +keycode 0x40 = Caps_Lock +keycode 0x01 = F1 + control keycode 0x01 = F1 + alt keycode 0x01 = Console_1 + control alt keycode 0x01 = Console_1 +keycode 0x02 = F2 + control keycode 0x02 = F2 + alt keycode 0x02 = Console_2 + control alt keycode 0x02 = Console_2 +keycode 0x03 = F3 + control keycode 0x03 = F3 + alt keycode 0x03 = Console_3 + control alt keycode 0x03 = Console_3 +keycode 0x04 = F4 + control keycode 0x04 = F4 + alt keycode 0x04 = Console_4 + control alt keycode 0x04 = Console_4 +keycode 0x05 = F5 + control keycode 0x05 = F5 + alt keycode 0x05 = Console_5 + control alt keycode 0x05 = Console_5 +keycode 0x06 = F6 + control keycode 0x06 = F6 + alt keycode 0x06 = Console_6 + control alt keycode 0x06 = Console_6 +keycode 0x07 = F7 + control keycode 0x07 = F7 + alt keycode 0x07 = Console_7 + control alt keycode 0x07 = Console_7 +keycode 0x08 = F8 + control keycode 0x08 = F8 + alt keycode 0x08 = Console_8 + control alt keycode 0x08 = Console_8 +keycode 0x09 = F9 + control keycode 0x09 = F9 + alt keycode 0x09 = Console_9 + control alt keycode 0x09 = Console_9 +keycode 0x0a = F10 + control keycode 0x0a = F10 + alt keycode 0x0a = Console_10 + control alt keycode 0x0a = Console_10 +keycode 0x0b = F11 + control keycode 0x0b = F11 + alt keycode 0x0b = Console_11 + control alt keycode 0x0b = Console_11 +keycode 0x0c = F12 + control keycode 0x0c = F12 + alt keycode 0x0c = Console_12 + control alt keycode 0x0c = Console_12 +keycode 0x0d = F13 + control keycode 0x0d = F13 + alt keycode 0x0d = Console_13 + control alt keycode 0x0d = Console_13 +keycode 0x0e = F14 + control keycode 0x0e = F14 + alt keycode 0x0e = Console_14 + control alt keycode 0x0e = Console_14 + +keycode 0x11 = F17 + control keycode 0x11 = F17 + alt keycode 0x11 = Console_17 + control alt keycode 0x11 = Console_17 +keycode 0x12 = F18 + control keycode 0x12 = F18 + alt keycode 0x12 = Console_18 + control alt keycode 0x12 = Console_18 +keycode 0x13 = F19 + control keycode 0x13 = F19 + alt keycode 0x13 = Console_19 + control alt keycode 0x13 = Console_19 +keycode 0x14 = F20 + control keycode 0x14 = F20 + alt keycode 0x14 = Console_20 + control alt keycode 0x14 = Console_20 + + +keycode 0x3b = KP_7 + alt keycode 0x3b = Ascii_7 + altgr keycode 0x3b = Hex_7 +keycode 0x3c = KP_8 + alt keycode 0x3c = Ascii_8 + altgr keycode 0x3c = Hex_8 +keycode 0x3d = KP_9 + alt keycode 0x3d = Ascii_9 + altgr keycode 0x3d = Hex_9 +keycode 0x3e = KP_Subtract +keycode 0x4e = KP_4 + alt keycode 0x4e = Ascii_4 + altgr keycode 0x4e = Hex_4 +keycode 0x4f = KP_5 + alt keycode 0x4f = Ascii_5 + altgr keycode 0x4f = Hex_5 +keycode 0x50 = KP_6 + alt keycode 0x50 = Ascii_6 + altgr keycode 0x50 = Hex_6 +keycode 0x62 = KP_1 + alt keycode 0x62 = Ascii_1 + altgr keycode 0x62 = Hex_1 +keycode 0x63 = KP_2 + alt keycode 0x63 = Ascii_2 + altgr keycode 0x63 = Hex_2 +keycode 0x64 = KP_3 + alt keycode 0x64 = Ascii_3 + altgr keycode 0x64 = Hex_3 +keycode 0x6b = KP_0 + alt keycode 0x6b = Ascii_0 + altgr keycode 0x6b = Hex_0 +keycode 0x6c = KP_Period +# altgr control keycode 0x6c = Boot + control alt keycode 0x6c = Boot +keycode 0x65 = KP_Enter + +keycode 0x3f = Control + +# keycode 100 = AltGr + +keycode 0x23 = Find +keycode 0x4d = Up +keycode 0x39 = Prior + shift keycode 0x39 = Scroll_Backward +keycode 0x5f = Left + alt keycode 0x5f = Decr_Console +keycode 0x61 = Right + alt keycode 0x61 = Incr_Console +keycode 0x38 = Select +keycode 0x60 = Down +keycode 0x3a = Next + shift keycode 0x3a = Scroll_Forward +keycode 0x24 = Insert +keycode 0x25 = Remove +# altgr control keycode 0x25 = Boot + control alt keycode 0x25 = Boot + +keycode 0x0f = Help Show_Memory Show_Registers + control keycode 0x0f = Show_State + +keycode 0x10 = Do + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -u --recursive --new-file v2.4.9/linux/drivers/tc/lk201-remap.c linux/drivers/tc/lk201-remap.c --- v2.4.9/linux/drivers/tc/lk201-remap.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/lk201-remap.c Mon Aug 27 08:56:31 2001 @@ -0,0 +1,172 @@ +/* + * Keyboard mappings for DEC LK201/401/501 keyboards + * + * 17.05.99 Michael Engel (engel@unix-ag.org) + * + * DEC US keyboards generate keycodes in the range 0x55 - 0xfb + * + * This conflicts with Linux scancode conventions which define + * 0x00-0x7f as "normal" and 0x80-0xff as "shifted" scancodes, so we + * have to remap the keycodes to 0x00-0x7f with the scancodeRemap + * array. The generated scancode is simply the number of the key counted + * from the left upper to the right lower corner of the keyboard ... + * + * These scancodes are then being remapped (I hope ;-)) with the + * lk501*map[] arrays which define scancode -> Linux code mapping + * + * Oh man is this horrible ;-) + * + * Scancodes with dual labels exist for keyboards as follows: + * + * code: left label / right label + * + * 0x73: LKx01, LK421 / LK443, LK444 + * 0x74: LKx01, LK421 / LK443, LK444 + * 0x7c: LKx01, LK421 / LK443, LK444 + * 0x8a: LKx01, LK421 / LK443, LK444 + * 0x8b: LKx01, LK421 / LK443, LK444 + * 0x8c: LKx01, LK421 / LK443, LK444 + * 0x8d: LKx01, LK421 / LK443, LK444 + * 0x8e: LKx01, LK421 / LK443, LK444 + * 0x8f: LKx01, LK421 / LK443, LK444 + * 0x9c: LKx01, LK421 / LK443, LK444 + * 0xa1: LKx01, LK421 / LK443, LK444 + * 0xa2: LKx01, LK421 / LK443, LK444 + * 0xa3: LKx01, LK421 / LK443, LK444 + * 0xa4: LKx01, LK421 / LK443, LK444 + * 0xad: LK421 / LK443, LK444 + * 0xc9: LKx01, LK421, LK443 / LK444 + * 0xf7: LKx01, LK443 / LK444 + */ + +unsigned char scancodeRemap[256] = { +/* ----- */ +/* 0 */ 0, 0, 0, 0, +/* ----- */ +/* 4 */ 0, 0, 0, 0, +/* ----- */ +/* 8 */ 0, 0, 0, 0, +/* ----- */ +/* c */ 0, 0, 0, 0, +/* ----- */ +/* 10 */ 0, 0, 0, 0, +/* ----- */ +/* 14 */ 0, 0, 0, 0, +/* ----- */ +/* 18 */ 0, 0, 0, 0, +/* ----- */ +/* 1c */ 0, 0, 0, 0, +/* ----- */ +/* 20 */ 0, 0, 0, 0, +/* ----- */ +/* 24 */ 0, 0, 0, 0, +/* ----- */ +/* 28 */ 0, 0, 0, 0, +/* ----- */ +/* 2c */ 0, 0, 0, 0, +/* ----- */ +/* 30 */ 0, 0, 0, 0, +/* ----- */ +/* 34 */ 0, 0, 0, 0, +/* ----- */ +/* 38 */ 0, 0, 0, 0, +/* ----- */ +/* 3c */ 0, 0, 0, 0, +/* ----- */ +/* 40 */ 0, 0, 0, 0, +/* ----- */ +/* 44 */ 0, 0, 0, 0, +/* ----- */ +/* 48 */ 0, 0, 0, 0, +/* ----- */ +/* 4c */ 0, 0, 0, 0, +/* ----- */ +/* 50 */ 0, 0, 0, 0, +/* ----- ESC F1 F2 */ +/* 54 */ 0, 0, 0x01, 0x02, +/* ----- F3 F4 F5 */ +/* 58 */ 0x03, 0x04, 0x05, 0, +/* ----- */ +/* 5c */ 0, 0, 0, 0, +/* ----- */ +/* 60 */ 0, 0, 0, 0, +/* ----- F6 F7 F8 F9 */ +/* 64 */ 0x06, 0x07, 0x08, 0x09, +/* ----- F10 */ +/* 68 */ 0x0a, 0, 0, 0, +/* ----- */ +/* 6c */ 0, 0, 0, 0, +/* ----- F11 F12 F13/PRNT SCRN */ +/* 70 */ 0, 0x0b, 0x0c, 0x0d, +/* ----- F14/SCRL LCK */ +/* 74 */ 0x0e, 0, 0, 0, +/* ----- */ +/* 78 */ 0, 0, 0, 0, +/* ----- HELP/PAUSE DO */ +/* 7c */ 0x0f, 0x10, 0, 0, +/* ----- F17 F18 F19 F20 */ +/* 80 */ 0x11, 0x12, 0x13, 0x14, +/* ----- */ +/* 84 */ 0, 0, 0, 0, +/* ----- FIND/INSERT INSERT/HOME */ +/* 88 */ 0, 0, 0x23, 0x24, +/* ----- REMOVE/PG UP SELECT/DELETE PREVIOUS/END NEXT/PG DN */ +/* 8c */ 0x25, 0x38, 0x39, 0x3a, +/* ----- KP 0 */ +/* 90 */ 0, 0, 0x6b, 0, +/* ----- KP . KP ENTER KP 1 KP 2 */ +/* 94 */ 0x6c, 0x65, 0x62, 0x63, +/* ----- KP 3 KP 4 KP 5 KP 6 */ +/* 98 */ 0x64, 0x4e, 0x4f, 0x50, +/* ----- KP ,/KP + KP 7 KP 8 KP 9 */ +/* 9c */ 0x51, 0x3b, 0x3c, 0x3d, +/* ----- KP - KP F1/NUM LCK KP F2/KP / KP F3/KP * */ +/* a0 */ 0x3e, 0x26, 0x27, 0x28, +/* ----- KP F4/KP - LEFT */ +/* a4 */ 0x29, 0, 0, 0x5f, +/* ----- RIGHT DOWN UP SHIFT Rt */ +/* a8 */ 0x61, 0x60, 0x4d, 0x5e, +/* ----- ALT COMP Rt/CTRL Rt SHIFT CONTROL */ +/* ac */ 0, 0, 0x52, 0x3f, +/* ----- CAPS COMPOSE ALT Rt */ +/* b0 */ 0x40, 0x67, 0, 0, +/* ----- */ +/* b4 */ 0, 0, 0, 0, +/* ----- */ +/* b8 */ 0, 0, 0, 0, +/* ----- BKSP RET TAB ` */ +/* bc */ 0x22, 0x37, 0x2a, 0x15, +/* ----- 1 q a z */ +/* c0 */ 0x16, 0x2b, 0x41, 0x54, +/* ----- 2 w s */ +/* c4 */ 0, 0x17, 0x2c, 0x42, +/* ----- x +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zs.h" +#include "lk201.h" + +/* Simple translation table for the SysRq keys */ + +#ifdef CONFIG_MAGIC_SYSRQ +/* + * Actually no translation at all, at least until we figure out + * how to define SysRq for LK201 and friends. --macro + */ +unsigned char lk201_sysrq_xlate[128]; +unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate; +#endif + +#define KEYB_LINE 3 + +static int __init lk201_init(struct dec_serial *); +static void __init lk201_info(struct dec_serial *); +static void lk201_kbd_rx_char(unsigned char, unsigned char); + +struct zs_hook lk201_kbdhook = { + init_channel: lk201_init, + init_info: lk201_info, + rx_char: NULL, + poll_rx_char: NULL, + poll_tx_char: NULL, + cflags: B4800 | CS8 | CSTOPB | CLOCAL +}; + +/* + * This is used during keyboard initialisation + */ +static unsigned char lk201_reset_string[] = { + LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */ + LK_CMD_SET_DEFAULTS, + LK_CMD_MODE(LK_MODE_RPT_DOWN, 1), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 2), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 3), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 4), + LK_CMD_MODE(LK_MODE_DOWN_UP, 5), + LK_CMD_MODE(LK_MODE_DOWN_UP, 6), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 7), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 8), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 9), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 10), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 11), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 12), + LK_CMD_MODE(LK_MODE_DOWN, 13), + LK_CMD_MODE(LK_MODE_RPT_DOWN, 14), + LK_CMD_ENB_RPT, + LK_CMD_DIS_KEYCLK, + LK_CMD_RESUME, + LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4), + LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf) +}; + +static int __init lk201_reset(struct dec_serial *info) +{ + int i; + + for (i = 0; i < sizeof(lk201_reset_string); i++) + if (info->hook->poll_tx_char(info, lk201_reset_string[i])) { + printk(__FUNCTION__" transmit timeout\n"); + return -EIO; + } + return 0; +} + +void kbd_leds(unsigned char leds) +{ + return; +} + +int kbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + return -EINVAL; +} + +int kbd_getkeycode(unsigned int scancode) +{ + return -EINVAL; +} + +int kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + *keycode = scancode; + return 1; +} + +char kbd_unexpected_up(unsigned char keycode) +{ + return 0x80; +} + +static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat) +{ + static int shift_state = 0; + static int prev_scancode; + unsigned char c = scancodeRemap[ch]; + + if (!stat || stat == 4) { + switch (ch) { + case LK_KEY_ACK: + break; + case LK_KEY_LOCK: + shift_state ^= LK_LOCK; + handle_scancode(c, shift_state && LK_LOCK ? 1 : 0); + break; + case LK_KEY_SHIFT: + shift_state ^= LK_SHIFT; + handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0); + break; + case LK_KEY_CTRL: + shift_state ^= LK_CTRL; + handle_scancode(c, shift_state && LK_CTRL ? 1 : 0); + break; + case LK_KEY_COMP: + shift_state ^= LK_COMP; + handle_scancode(c, shift_state && LK_COMP ? 1 : 0); + break; + case LK_KEY_RELEASE: + if (shift_state & LK_SHIFT) + handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0); + if (shift_state & LK_CTRL) + handle_scancode(scancodeRemap[LK_KEY_CTRL], 0); + if (shift_state & LK_COMP) + handle_scancode(scancodeRemap[LK_KEY_COMP], 0); + if (shift_state & LK_LOCK) + handle_scancode(scancodeRemap[LK_KEY_LOCK], 0); + shift_state = 0; + break; + case LK_KEY_REPEAT: + handle_scancode(prev_scancode, 1); + break; + default: + prev_scancode = c; + handle_scancode(c, 1); + break; + } + } else + printk("Error reading LKx01 keyboard: 0x%02x\n", stat); +} + +static void __init lk201_info(struct dec_serial *info) +{ +} + +static int __init lk201_init(struct dec_serial *info) +{ + unsigned int ch, id = 0; + int result; + + printk("DECstation LK keyboard driver v0.04... "); + + result = lk201_reset(info); + if (result) + return result; + mdelay(10); + + /* + * Detect whether there is an LK201 or an LK401 + * The LK401 has ALT keys... + */ + info->hook->poll_tx_char(info, LK_CMD_REQ_ID); + while ((ch = info->hook->poll_rx_char(info)) > 0) + id = ch; + + switch (id) { + case 1: + printk("LK201 detected\n"); + break; + case 2: + printk("LK401 detected\n"); + break; + default: + printk("unknown keyboard, ID %d,\n", id); + printk("... please report to \n"); + } + + /* + * now we're ready + */ + info->hook->rx_char = lk201_kbd_rx_char; + + return 0; +} + +void __init kbd_init_hw(void) +{ + extern int register_zs_hook(unsigned int, struct zs_hook *); + extern int unregister_zs_hook(unsigned int); + + if (TURBOCHANNEL) { + if (mips_machtype != MACH_DS5000_XX) { + /* + * This is not a MAXINE, so: + * + * kbd_init_hw() is being called before + * rs_init() so just register the kbd hook + * and let zs_init do the rest :-) + */ + if (mips_machtype == MACH_DS5000_200) + printk("LK201 Support for DS5000/200 not yet ready ...\n"); + else + if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook)) + unregister_zs_hook(KEYB_LINE); + } + } else { + /* + * TODO: modify dz.c to allow similar hooks + * for LK201 handling on DS2100, DS3100, and DS5000/200 + */ + printk("LK201 Support for DS3100 not yet ready ...\n"); + } +} + + + + diff -u --recursive --new-file v2.4.9/linux/drivers/tc/lk201.h linux/drivers/tc/lk201.h --- v2.4.9/linux/drivers/tc/lk201.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/tc/lk201.h Mon Aug 27 08:56:31 2001 @@ -0,0 +1,53 @@ +/* + * Commands to the keyboard processor + */ + +#define LK_PARAM 0x80 /* start/end parameter list */ + +#define LK_CMD_RESUME 0x8b +#define LK_CMD_INHIBIT 0xb9 +#define LK_CMD_LEDS_ON 0x13 /* 1 param: led bitmask */ +#define LK_CMD_LEDS_OFF 0x11 /* 1 param: led bitmask */ +#define LK_CMD_DIS_KEYCLK 0x99 +#define LK_CMD_ENB_KEYCLK 0x1b /* 1 param: volume */ +#define LK_CMD_DIS_CTLCLK 0xb9 +#define LK_CMD_ENB_CTLCLK 0xbb +#define LK_CMD_SOUND_CLK 0x9f +#define LK_CMD_DIS_BELL 0xa1 +#define LK_CMD_ENB_BELL 0x23 /* 1 param: volume */ +#define LK_CMD_BELL 0xa7 +#define LK_CMD_TMP_NORPT 0xc1 +#define LK_CMD_ENB_RPT 0xe3 +#define LK_CMD_DIS_RPT 0xe1 +#define LK_CMD_RPT_TO_DOWN 0xd9 +#define LK_CMD_REQ_ID 0xab +#define LK_CMD_POWER_UP 0xfd +#define LK_CMD_TEST_MODE 0xcb +#define LK_CMD_SET_DEFAULTS 0xd3 + +/* there are 4 leds, represent them in the low 4 bits of a byte */ +#define LK_PARAM_LED_MASK(ledbmap) (LK_PARAM|(ledbmap)) + +/* max volume is 0, lowest is 0x7 */ +#define LK_PARAM_VOLUME(v) (LK_PARAM|((v)&0x7)) + +/* mode set command(s) details */ +#define LK_MODE_DOWN 0x0 +#define LK_MODE_RPT_DOWN 0x2 +#define LK_MODE_DOWN_UP 0x6 +#define LK_CMD_MODE(m,div) (LK_PARAM|(div<<3)|m) + +#define LK_SHIFT 1<<0 +#define LK_CTRL 1<<1 +#define LK_LOCK 1<<2 +#define LK_COMP 1<<3 + +#define LK_KEY_SHIFT 174 +#define LK_KEY_CTRL 175 +#define LK_KEY_LOCK 176 +#define LK_KEY_COMP 177 +#define LK_KEY_RELEASE 179 +#define LK_KEY_REPEAT 180 +#define LK_KEY_ACK 186 + +extern unsigned char scancodeRemap[256]; \ No newline at end of file diff -u --recursive --new-file v2.4.9/linux/drivers/tc/tc.c linux/drivers/tc/tc.c --- v2.4.9/linux/drivers/tc/tc.c Sat May 13 08:31:25 2000 +++ linux/drivers/tc/tc.c Mon Aug 27 08:56:31 2001 @@ -1,4 +1,4 @@ -/* $Id: tc.c,v 1.3 1999/10/09 00:01:32 ralf Exp $ +/* * tc-init: We assume the TURBOchannel to be up and running so * just probe for Modules and fill in the global data structure * tc_bus. @@ -8,9 +8,7 @@ * for more details. * * Copyright (c) Harald Koerfgen, 1998 - * */ - #include #include #include @@ -23,14 +21,15 @@ #include #include +#include #define TC_DEBUG slot_info tc_bus[MAX_SLOT]; -static int max_tcslot = 0; -static tcinfo *info = (tcinfo *)0; +static int max_tcslot; +static tcinfo *info; -unsigned long system_base = 0; +unsigned long system_base; extern void (*dbe_board_handler)(struct pt_regs *regs); extern unsigned long *(*rex_slot_address)(int); @@ -112,19 +111,19 @@ for (slot = 0; slot <= max_slot; slot++) { module = (char *)(startaddr + slot * size); offset = -1; - if (module[OLDCARD + PATTERN0] == 0x55 && module[OLDCARD + PATTERN1] == 0x00 - && module[OLDCARD + PATTERN2] == 0xaa && module[OLDCARD + PATTERN3] == 0xff) + if (module[OLDCARD + TC_PATTERN0] == 0x55 && module[OLDCARD + TC_PATTERN1] == 0x00 + && module[OLDCARD + TC_PATTERN2] == 0xaa && module[OLDCARD + TC_PATTERN3] == 0xff) offset = OLDCARD; - if (module[PATTERN0] == 0x55 && module[PATTERN1] == 0x00 - && module[PATTERN2] == 0xaa && module[PATTERN3] == 0xff) + if (module[TC_PATTERN0] == 0x55 && module[TC_PATTERN1] == 0x00 + && module[TC_PATTERN2] == 0xaa && module[TC_PATTERN3] == 0xff) offset = 0; if (offset != -1) { tc_bus[slot].base_addr = (unsigned long)module; for(i = 0; i < 8; i++) { - tc_bus[slot].firmware[i] = module[FIRM_VER + offset + 4 * i]; - tc_bus[slot].vendor[i] = module[VENDOR + offset + 4 * i]; - tc_bus[slot].name[i] = module[MODULE + offset + 4 * i]; + tc_bus[slot].firmware[i] = module[TC_FIRM_VER + offset + 4 * i]; + tc_bus[slot].vendor[i] = module[TC_VENDOR + offset + 4 * i]; + tc_bus[slot].name[i] = module[TC_MODULE + offset + 4 * i]; } tc_bus[slot].firmware[8] = 0; tc_bus[slot].vendor[8] = 0; @@ -206,7 +205,7 @@ if (TURBOCHANNEL && info->slot_size && slot0addr) { printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision, tc_clock / 10, tc_clock % 10); - printk("(%sparity)\n", info->parity ? "" : "no "); + printk("(with%s parity)\n", info->parity ? "" : "out"); slot_size = info->slot_size << 20; @@ -235,3 +234,11 @@ ioport_resource.end = KSEG2 - 1; } } + +EXPORT_SYMBOL(search_tc_card); +EXPORT_SYMBOL(claim_tc_card); +EXPORT_SYMBOL(release_tc_card); +EXPORT_SYMBOL(get_tc_base_addr); +EXPORT_SYMBOL(get_tc_irq_nr); +EXPORT_SYMBOL(get_tc_speed); + diff -u --recursive --new-file v2.4.9/linux/drivers/tc/tcsyms.c linux/drivers/tc/tcsyms.c --- v2.4.9/linux/drivers/tc/tcsyms.c Sat May 13 08:31:25 2000 +++ linux/drivers/tc/tcsyms.c Wed Dec 31 16:00:00 1969 @@ -1,14 +0,0 @@ -/* - * TURBOchannel Services -- Exported Symbols - * - */ - -#include -#include - -EXPORT_SYMBOL(search_tc_card); -EXPORT_SYMBOL(claim_tc_card); -EXPORT_SYMBOL(release_tc_card); -EXPORT_SYMBOL(get_tc_base_addr); -EXPORT_SYMBOL(get_tc_irq_nr); -EXPORT_SYMBOL(get_tc_speed); diff -u --recursive --new-file v2.4.9/linux/drivers/tc/zs.c linux/drivers/tc/zs.c --- v2.4.9/linux/drivers/tc/zs.c Thu Oct 12 14:20:47 2000 +++ linux/drivers/tc/zs.c Mon Aug 27 08:56:31 2001 @@ -1,22 +1,46 @@ /* - * decserial.c: Serial port driver for IOASIC DECsatations. + * decserial.c: Serial port driver for IOASIC DECstations. * - * Derived from drivers/macintosh/macserial.c by Harald Koerfgen. * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * Derived from drivers/macintosh/macserial.c by Harald Koerfgen. * * DECstation changes - * Copyright (C) 1998 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * Copyright (C) 1998-2000 Harald Koerfgen + * Copyright (C) 2000,2001 Maciej W. Rozycki * * For the rest of the code the original Copyright applies: * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * - * Keyboard and mouse are not supported right now. If you want to change this, - * you might want to have a look at drivers/sbus/char/sunserial.c to see - * how this might be done. HK + * + * Note: for IOASIC systems the wiring is as follows: + * + * mouse/keyboard: + * DIN-7 MJ-4 signal SCC + * 2 1 TxD <- A.TxD + * 3 4 RxD -> A.RxD + * + * EIA-232/EIA-423: + * DB-25 MMJ-6 signal SCC + * 2 2 TxD <- B.TxD + * 3 5 RxD -> B.RxD + * 4 RTS <- ~A.RTS + * 5 CTS -> ~B.CTS + * 6 6 DSR -> ~A.SYNC + * 8 CD -> ~B.DCD + * 12 DSRS(DCE) -> ~A.CTS (*) + * 15 TxC -> B.TxC + * 17 RxC -> B.RxC + * 20 1 DTR <- ~A.DTR + * 22 RI -> ~A.DCD + * 23 DSRS(DTE) <- ~B.RTS + * + * (*) EIA-232 defines the signal at this pin to be SCD, while DSRS(DCE) + * is shared with DSRS(DTE) at pin 23. */ #include +#include #include #include #include @@ -31,6 +55,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_CONSOLE #include #endif @@ -43,17 +68,26 @@ #include #include #include +#include +#ifdef CONFIG_DECSTATION #include #include #include #include +#endif +#ifdef CONFIG_BAGET_MIPS +#include +unsigned long system_base; +#endif #ifdef CONFIG_KGDB #include #endif +#ifdef CONFIG_MAGIC_SYSRQ +#include +#endif #include "zs.h" - /* * It would be nice to dynamically allocate everything that * depends on NUM_SERIAL, so we could support any number of @@ -61,11 +95,60 @@ */ #define NUM_SERIAL 2 /* Max number of ZS chips supported */ #define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ +#define CHANNEL_A_NR (zs_parms->channel_a_offset > zs_parms->channel_b_offset) + /* Number of channel A in the chip */ +#define ZS_CHAN_IO_SIZE 8 +#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ #define RECOVERY_DELAY udelay(2) -struct dec_zschannel zs_channels[NUM_CHANNELS]; +struct zs_parms { + unsigned long scc0; + unsigned long scc1; + int channel_a_offset; + int channel_b_offset; + int irq; + int clock; +}; +static struct zs_parms *zs_parms; + +#ifdef CONFIG_DECSTATION +static struct zs_parms ds_parms = { + scc0 : SCC0, + scc1 : SCC1, + channel_a_offset : 1, + channel_b_offset : 9, + irq : SERIAL, + clock : ZS_CLOCK +}; +#endif +#ifdef CONFIG_BAGET_MIPS +static struct zs_parms baget_parms = { + scc0 : UNI_SCC0, + scc1 : UNI_SCC1, + channel_a_offset : 9, + channel_b_offset : 1, + irq : BAGET_SCC_IRQ, + clock : 14745000 +}; +#endif + +#ifdef CONFIG_DECSTATION +#define DS_BUS_PRESENT (IOASIC) +#else +#define DS_BUS_PRESENT 0 +#endif + +#ifdef CONFIG_BAGET_MIPS +#define BAGET_BUS_PRESENT (mips_machtype == MACH_BAGET202) +#else +#define BAGET_BUS_PRESENT 0 +#endif + +#define BUS_PRESENT (DS_BUS_PRESENT || BAGET_BUS_PRESENT) + +struct dec_zschannel zs_channels[NUM_CHANNELS]; struct dec_serial zs_soft[NUM_CHANNELS]; int zs_channels_found; struct dec_serial *zs_chain; /* list of all channels */ @@ -75,19 +158,9 @@ #ifdef CONFIG_SERIAL_CONSOLE static struct console sercons; #endif - -#ifdef CONFIG_KGDB -struct dec_zschannel *zs_kgdbchan; -static unsigned char scc_inittab[] = { - 9, 0x80, /* reset A side (CHRA) */ - 13, 0, /* set baud rate divisor */ - 12, 1, - 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ - 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ - 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ - 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ - 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ -}; +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) \ + && !defined(MODULE) +static unsigned long break_pressed; /* break, really ... */ #endif static unsigned char zs_init_regs[16] __initdata = { @@ -106,8 +179,6 @@ 0 /* write 15 */ }; -#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ - DECLARE_TASK_QUEUE(tq_zs_serial); struct tty_driver serial_driver, callout_driver; @@ -129,6 +200,12 @@ #undef SERIAL_DEBUG_THROTTLE #undef SERIAL_PARANOIA_CHECK +#undef ZS_DEBUG_REGS + +#ifdef SERIAL_DEBUG_THROTTLE +#define _tty_name(tty,buf) tty_name(tty,buf) +#endif + #define RS_STROBE_TIME 10 #define RS_ISR_PASS_LIMIT 256 @@ -184,7 +261,7 @@ */ static int baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 0, 0 }; + 9600, 19200, 38400, 57600, 115200, 0 }; /* * Reading and writing Z8530 registers. @@ -256,16 +333,21 @@ } /* Sets or clears DTR/RTS on the requested line */ -static inline void zs_rtsdtr(struct dec_serial *ss, int set) +static inline void zs_rtsdtr(struct dec_serial *info, int which, int set) { - if (ss->zs_channel != ss->zs_chan_a) { - if (set) - ss->zs_chan_a->curregs[5] |= (RTS | DTR); - else - ss->zs_chan_a->curregs[5] &= ~(RTS | DTR); - write_zsreg(ss->zs_chan_a, 5, ss->zs_chan_a->curregs[5]); + unsigned long flags; + + + save_flags(flags); cli(); + if (info->zs_channel != info->zs_chan_a) { + if (set) { + info->zs_chan_a->curregs[5] |= (which & (RTS | DTR)); + } else { + info->zs_chan_a->curregs[5] &= ~(which & (RTS | DTR)); + } + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); } - return; + restore_flags(flags); } /* Utility routines for the Zilog */ @@ -281,7 +363,7 @@ */ brg = (read_zsreg(channel, 13) << 8); brg |= read_zsreg(channel, 12); - return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); + return BRG_TO_BPS(brg, (zs_parms->clock/(ss->clk_divisor))); } /* On receive, this clears errors and the receiver interrupts */ @@ -302,6 +384,8 @@ * ----------------------------------------------------------------------- */ +static int tty_break; /* Set whenever BREAK condition is detected. */ + /* * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. @@ -320,23 +404,59 @@ struct tty_struct *tty = info->tty; unsigned char ch, stat, flag; - while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { + while ((read_zsreg(info->zs_channel, R0) & Rx_CH_AV) != 0) { stat = read_zsreg(info->zs_channel, R1); ch = read_zsdata(info->zs_channel); -#ifdef CONFIG_KGDB - if (info->kgdb_channel) { - if (ch == 0x03 || ch == '$') - breakpoint(); - if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) - write_zsreg(info->zs_channel, 0, ERR_RES); - return; + if (!tty && !info->hook && !info->hook->rx_char) + continue; + + if (tty_break) { + tty_break = 0; +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) + if (info->line == sercons.index) { + if (!break_pressed) { + break_pressed = jiffies; + goto ignore_char; + } + break_pressed = 0; + } +#endif + flag = TTY_BREAK; + if (info->flags & ZILOG_SAK) + do_SAK(tty); + } else { + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + } else if (stat & FRM_ERR) { + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + } else + flag = 0; + if (flag) + /* reset the error indication */ + write_zsreg(info->zs_channel, R0, ERR_RES); + } + +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) + if (break_pressed && info->line == sercons.index) { + if (ch != 0 && + time_before(jiffies, break_pressed + HZ*5)) { + handle_sysrq(ch, regs, NULL, NULL); + break_pressed = 0; + goto ignore_char; + } + break_pressed = 0; } #endif - if (!tty) - continue; + if (info->hook && info->hook->rx_char) { + (*info->hook->rx_char)(ch, flag); + return; + } + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { static int flip_buf_ovf; ++flip_buf_ovf; @@ -348,26 +468,18 @@ if (flip_max_cnt < tty->flip.count) flip_max_cnt = tty->flip.count; } - if (stat & Rx_OVR) { - flag = TTY_OVERRUN; - } else if (stat & FRM_ERR) { - flag = TTY_FRAME; - } else if (stat & PAR_ERR) { - flag = TTY_PARITY; - } else - flag = 0; - if (flag) - /* reset the error indication */ - write_zsreg(info->zs_channel, 0, ERR_RES); + *tty->flip.flag_buf_ptr++ = flag; *tty->flip.char_buf_ptr++ = ch; + ignore_char: } - tty_flip_buffer_push(tty); + if (tty) + tty_flip_buffer_push(tty); } static void transmit_chars(struct dec_serial *info) { - if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) + if ((read_zsreg(info->zs_channel, R0) & Tx_BUF_EMP) == 0) return; info->tx_active = 0; @@ -379,8 +491,9 @@ return; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { - write_zsreg(info->zs_channel, 0, RES_Tx_P); + if ((info->xmit_cnt <= 0) || (info->tty && info->tty->stopped) + || info->tx_stopped) { + write_zsreg(info->zs_channel, R0, RES_Tx_P); return; } /* Send char */ @@ -395,45 +508,48 @@ static _INLINE_ void status_handle(struct dec_serial *info) { - unsigned char status; + unsigned char stat; /* Get status from Read Register 0 */ - status = read_zsreg(info->zs_channel, 0); + stat = read_zsreg(info->zs_channel, R0); + + if (stat & BRK_ABRT) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + tty_break = 1; + } - /* FIXEM: Check for DCD transitions */ - if (((status ^ info->read_reg_zero) & DCD) != 0 - && info->tty && !C_CLOCAL(info->tty)) { - if (status & DCD) { - wake_up_interruptible(&info->open_wait); - } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { - if (info->tty) + if (info->zs_channel != info->zs_chan_a) { + + /* FIXEM: Check for DCD transitions */ + if (((stat ^ info->read_reg_zero) & DCD) != 0 + && info->tty && !C_CLOCAL(info->tty)) { + if (stat & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { tty_hangup(info->tty); + } } - } - /* Check for CTS transitions */ - if (info->tty && C_CRTSCTS(info->tty)) { - /* - * For some reason, on the Power Macintosh, - * it seems that the CTS bit is 1 when CTS is - * *negated* and 0 when it is asserted. - * The DCD bit doesn't seem to be inverted - * like this. - */ - if ((status & CTS) != 0) { - if (info->tx_stopped) { - info->tx_stopped = 0; - if (!info->tx_active) - transmit_chars(info); + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + if ((stat & CTS) != 0) { + if (info->tx_stopped) { + info->tx_stopped = 0; + if (!info->tx_active) + transmit_chars(info); + } + } else { + info->tx_stopped = 1; } - } else { - info->tx_stopped = 1; } + } /* Clear status condition... */ - write_zsreg(info->zs_channel, 0, RES_EXT_INT); - info->read_reg_zero = status; + write_zsreg(info->zs_channel, R0, RES_EXT_INT); + info->read_reg_zero = stat; } /* @@ -459,7 +575,7 @@ shift = 0; /* Channel B */ for (;;) { - zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; + zs_intreg = read_zsreg(info->zs_chan_a, R3) >> shift; if ((zs_intreg & CHAN_IRQMASK) == 0) break; @@ -473,8 +589,31 @@ status_handle(info); } } + + /* Why do we need this ? */ + write_zsreg(info->zs_channel, 0, RES_H_IUS); } +#ifdef ZS_DEBUG_REGS +void zs_dump (void) { + int i, j; + for (i = 0; i < zs_channels_found; i++) { + struct dec_zschannel *ch = &zs_channels[i]; + if ((long)ch->control == UNI_IO_BASE+UNI_SCC1A_CTRL) { + for (j = 0; j < 15; j++) { + printk("W%d = 0x%x\t", + j, (int)ch->curregs[j]); + } + for (j = 0; j < 15; j++) { + printk("R%d = 0x%x\t", + j, (int)read_zsreg(ch,j)); + } + printk("\n\n"); + } + } +} +#endif + /* * ------------------------------------------------------------------- * Here ends the serial interrupt routines. @@ -559,7 +698,7 @@ } } -static int startup(struct dec_serial * info) +int zs_startup(struct dec_serial * info) { unsigned long flags; @@ -575,7 +714,7 @@ save_flags(flags); cli(); #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%d (irq %d)...", info->line, info->irq); + printk("starting up ttyS%02d (irq %d)...", info->line, info->irq); #endif /* @@ -593,7 +732,7 @@ /* * Turn on RTS and DTR. */ - zs_rtsdtr(info, 1); + zs_rtsdtr(info, RTS | DTR, 1); /* * Finally, enable sequencing and interrupts @@ -664,8 +803,7 @@ info->zs_channel->curregs[5] &= ~TxENAB; write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); if (!info->tty || C_HUPCL(info->tty)) { - info->zs_chan_a->curregs[5] &= ~(DTR | RTS); - write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + zs_rtsdtr(info, RTS | DTR, 0); } if (info->tty) @@ -681,29 +819,45 @@ */ static void change_speed(struct dec_serial *info) { - unsigned short port; unsigned cflag; int i; - int brg; + int brg, bits; unsigned long flags; - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - if (!(port = info->port)) - return; + if (!info->hook) { + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!info->port) + return; + } else { + cflag = info->hook->cflags; + } + i = cflag & CBAUD; + if (i & CBAUDEX) { + i &= ~CBAUDEX; + if (i < 1 || i > 2) { + if (!info->hook) + info->tty->termios->c_cflag &= ~CBAUDEX; + else + info->hook->cflags &= ~CBAUDEX; + } else + i += 15; + } save_flags(flags); cli(); info->zs_baud = baud_table[i]; info->clk_divisor = 16; - - switch (info->zs_baud) { - default: + if (info->zs_baud) { info->zs_channel->curregs[4] = X16CLK; - brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); + brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); info->zs_channel->curregs[12] = (brg & 255); info->zs_channel->curregs[13] = ((brg >> 8) & 255); + zs_rtsdtr(info, DTR, 1); + } else { + zs_rtsdtr(info, RTS | DTR, 0); + return; } /* byte size and parity */ @@ -711,24 +865,31 @@ info->zs_channel->curregs[5] &= ~TxNBITS_MASK; switch (cflag & CSIZE) { case CS5: + bits = 7; info->zs_channel->curregs[3] |= Rx5; info->zs_channel->curregs[5] |= Tx5; break; case CS6: + bits = 8; info->zs_channel->curregs[3] |= Rx6; info->zs_channel->curregs[5] |= Tx6; break; case CS7: + bits = 9; info->zs_channel->curregs[3] |= Rx7; info->zs_channel->curregs[5] |= Tx7; break; case CS8: default: /* defaults to 8 bits */ + bits = 10; info->zs_channel->curregs[3] |= Rx8; info->zs_channel->curregs[5] |= Tx8; break; } + info->timeout = ((info->xmit_fifo_size*HZ*bits) / info->zs_baud); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + info->zs_channel->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); if (cflag & CSTOPB) { info->zs_channel->curregs[4] |= SB2; @@ -750,7 +911,7 @@ info->zs_channel->curregs[15] &= ~DCDIE; if (cflag & CRTSCTS) { info->zs_channel->curregs[15] |= CTSIE; - if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + if ((read_zsreg(info->zs_channel, 0) & CTS) == 0) info->tx_stopped = 1; } else { info->zs_channel->curregs[15] &= ~CTSIE; @@ -895,17 +1056,7 @@ } if (C_CRTSCTS(tty)) { - /* - * Here we want to turn off the RTS line. On Macintoshes, - * we only get the DTR line, which goes to both DTR and - * RTS on the modem. RTS doesn't go out to the serial - * port socket. So you should make sure your modem is - * set to ignore DTR if you're using CRTSCTS. - */ - save_flags(flags); cli(); - info->zs_chan_a->curregs[5] &= ~(DTR | RTS); - write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); - restore_flags(flags); + zs_rtsdtr(info, RTS, 0); } } @@ -937,11 +1088,7 @@ } if (C_CRTSCTS(tty)) { - /* Assert RTS and DTR lines */ - save_flags(flags); cli(); - info->zs_chan_a->curregs[5] |= DTR | RTS; - write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); - restore_flags(flags); + zs_rtsdtr(info, RTS, 1); } } @@ -983,7 +1130,7 @@ copy_from_user(&new_serial,new_info,sizeof(new_serial)); old_info = *info; - if (!suser()) { + if (!capable(CAP_SYS_ADMIN)) { if ((new_serial.baud_base != info->baud_base) || (new_serial.type != info->type) || (new_serial.close_delay != info->close_delay) || @@ -1012,7 +1159,7 @@ info->closing_wait = new_serial.closing_wait; check_and_exit: - retval = startup(info); + retval = zs_startup(info); return retval; } @@ -1039,18 +1186,25 @@ static int get_modem_info(struct dec_serial *info, unsigned int *value) { - unsigned char control, status; + unsigned char control, status_a, status_b; unsigned int result; - cli(); - control = info->zs_chan_a->curregs[5]; - status = read_zsreg(info->zs_channel, 0); - sti(); - result = ((control & RTS) ? TIOCM_RTS: 0) - | ((control & DTR) ? TIOCM_DTR: 0) - | ((status & DCD) ? TIOCM_CAR: 0) - | ((status & CTS) ? 0: TIOCM_CTS); - put_user(result,value); + if (info->zs_channel == info->zs_chan_a) + result = 0; + else { + cli(); + control = info->zs_chan_a->curregs[5]; + status_a = read_zsreg(info->zs_chan_a, 0); + status_b = read_zsreg(info->zs_channel, 0); + sti(); + result = ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status_b & DCD) ? TIOCM_CAR: 0) + | ((status_a & DCD) ? TIOCM_RNG: 0) + | ((status_a & SYNC_HUNT) ? TIOCM_DSR: 0) + | ((status_b & CTS) ? TIOCM_CTS: 0); + } + put_user(result, value); return 0; } @@ -1063,6 +1217,10 @@ error = verify_area(VERIFY_READ, value, sizeof(int)); if (error) return error; + + if (info->zs_channel == info->zs_chan_a) + return 0; + get_user(arg, value); bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); cli(); @@ -1074,7 +1232,8 @@ info->zs_chan_a->curregs[5] &= ~bits; break; case TIOCMSET: - info->zs_chan_a->curregs[5] = (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; + info->zs_chan_a->curregs[5] = + (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; break; default: sti(); @@ -1113,10 +1272,9 @@ int error; struct dec_serial * info = (struct dec_serial *)tty->driver_data; -#ifdef CONFIG_KGDB - if (info->kgdb_channel) + if (info->hook) return -ENODEV; -#endif + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) return -ENODEV; @@ -1210,7 +1368,7 @@ } #ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", info->line, info->count); + printk("rs_close ttyS%02d, count = %d\n", info->line, info->count); #endif if ((tty->count == 1) && (info->count != 1)) { /* @@ -1225,7 +1383,7 @@ info->count = 1; } if (--info->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", + printk("rs_close: bad serial port count for ttyS%02d: %d\n", info->line, info->count); info->count = 0; } @@ -1415,7 +1573,7 @@ retval = 0; add_wait_queue(&info->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttys%d, count = %d\n", + printk("block_til_ready before block: ttyS%02d, count = %d\n", info->line, info->count); #endif cli(); @@ -1427,7 +1585,7 @@ cli(); if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && (tty->termios->c_cflag & CBAUD)) - zs_rtsdtr(info, 1); + zs_rtsdtr(info, RTS | DTR, 1); sti(); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || @@ -1451,7 +1609,7 @@ break; } #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttys%d, count = %d\n", + printk("block_til_ready blocking: ttyS%02d, count = %d\n", info->line, info->count); #endif schedule(); @@ -1462,7 +1620,7 @@ info->count++; info->blocked_open--; #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttys%d, count = %d\n", + printk("block_til_ready after blocking: ttyS%02d, count = %d\n", info->line, info->count); #endif if (retval) @@ -1487,10 +1645,9 @@ return -ENODEV; info = zs_soft + line; -#ifdef CONFIG_KGDB - if (info->kgdb_channel) + if (info->hook) return -ENODEV; -#endif + if (serial_paranoia_check(info, tty->device, "rs_open")) return -ENODEV; #ifdef SERIAL_DEBUG_OPEN @@ -1520,7 +1677,7 @@ /* * Start up serial port */ - retval = startup(info); + retval = zs_startup(info); if (retval) return retval; @@ -1552,7 +1709,7 @@ info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttys%d successful...", info->line); + printk("rs_open ttyS%02d successful...", info->line); #endif /* tty->low_latency = 1; */ return 0; @@ -1562,7 +1719,7 @@ static void __init show_serial_version(void) { - printk("DECstation Z8530 serial driver version 0.03\n"); + printk("DECstation Z8530 serial driver version 0.05\n"); } /* Initialize Z8530s zs_channels @@ -1576,7 +1733,7 @@ /* * did we get here by accident? */ - if(!IOASIC) { + if(!BUS_PRESENT) { printk("Not on JUNKIO machine, skipping probe_sccs\n"); return; } @@ -1587,19 +1744,36 @@ * system_base for this case :-(. HK */ switch(mips_machtype) { +#ifdef CONFIG_DECSTATION case MACH_DS5000_2X0: system_base = 0xbf800000; n_chips = 2; + zs_parms = &ds_parms; break; case MACH_DS5000_1XX: system_base = 0xbc000000; n_chips = 2; + zs_parms = &ds_parms; break; case MACH_DS5000_XX: system_base = 0xbc000000; n_chips = 1; + zs_parms = &ds_parms; + break; +#endif +#ifdef CONFIG_BAGET_MIPS + case MACH_BAGET202: + system_base = UNI_IO_BASE; + n_chips = 2; + zs_parms = &baget_parms; + zs_init_regs[2] = 0x8; break; +#endif + default: + panic("zs: unsupported bus"); } + if (!zs_parms) + panic("zs: uninitialized parms"); pp = &zs_chain; @@ -1610,16 +1784,44 @@ /* * The sccs reside on the high byte of the 16 bit IOBUS */ - zs_channels[n_channels].control = (volatile unsigned char *) - system_base + (0 == chip ? SCC0 : SCC1) + (0 == channel ? 1 : 9); - zs_channels[n_channels].data = zs_channels[n_channels].control + 4; + zs_channels[n_channels].control = + (volatile unsigned char *)system_base + + (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + + (0 == channel ? zs_parms->channel_a_offset : + zs_parms->channel_b_offset); + zs_channels[n_channels].data = + zs_channels[n_channels].control + 4; + +#ifndef CONFIG_SERIAL_CONSOLE + /* + * We're called early and memory managment isn't up, yet. + * Thus check_region would fail. + */ + if (check_region((unsigned long) + zs_channels[n_channels].control, + ZS_CHAN_IO_SIZE) < 0) { + panic("SCC I/O region is not free"); + } + request_region((unsigned long) + zs_channels[n_channels].control, + ZS_CHAN_IO_SIZE, "SCC"); +#endif zs_soft[n_channels].zs_channel = &zs_channels[n_channels]; - zs_soft[n_channels].irq = SERIAL; + zs_soft[n_channels].irq = zs_parms->irq; - if (0 == channel) - zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1]; + /* + * Identification of channel A. Location of channel A + * inside chip depends on mapping of internal address + * the chip decodes channels by. + * CHANNEL_A_NR returns either 0 (in case of + * DECstations) or 1 (in case of Baget). + */ + if (CHANNEL_A_NR == channel) + zs_soft[n_channels].zs_chan_a = + &zs_channels[n_channels+1-2*CHANNEL_A_NR]; else - zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels]; + zs_soft[n_channels].zs_chan_a = + &zs_channels[n_channels]; *pp = &zs_soft[n_channels]; pp = &zs_soft[n_channels].zs_next; @@ -1639,9 +1841,9 @@ /* save_and_cli(flags); for (n = 0; n < zs_channels_found; n++) { if (((int)zs_channels[n].control & 0xf) == 1) { - write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES); - udelay(10000); - write_zsreg(zs_soft[channel].zs_chan_a, R9, 0); + write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); + mdelay(10); + write_zsreg(zs_soft[n].zs_chan_a, R9, 0); } load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs); } @@ -1655,7 +1857,7 @@ unsigned long flags; struct dec_serial *info; - if(!IOASIC) + if(!BUS_PRESENT) return -ENODEV; /* Setup base handler, and timer table. */ @@ -1672,7 +1874,11 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) + serial_driver.name = "tts/%d"; +#else serial_driver.name = "ttyS"; +#endif serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; serial_driver.num = zs_channels_found; @@ -1682,7 +1888,7 @@ serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; serial_driver.refcount = &serial_refcount; serial_driver.table = serial_table; serial_driver.termios = serial_termios; @@ -1710,7 +1916,11 @@ * major number and the subtype code. */ callout_driver = serial_driver; +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) + callout_driver.name = "cua/%d"; +#else callout_driver.name = "cua"; +#endif callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; @@ -1722,36 +1932,26 @@ save_flags(flags); cli(); for (channel = 0; channel < zs_channels_found; ++channel) { -#ifdef CONFIG_KGDB - if (zs_soft[channel].kgdb_channel) { - continue; - } -#endif + if (zs_soft[channel].hook && + zs_soft[channel].hook->init_channel) + (*zs_soft[channel].hook->init_channel) + (&zs_soft[channel]); + zs_soft[channel].clk_divisor = 16; zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ, + if (request_irq(zs_parms->irq, rs_interrupt, SA_SHIRQ, "SCC", &zs_soft[channel])) printk(KERN_ERR "decserial: can't get irq %d\n", - SERIAL); - - /* If console serial line, then enable interrupts. */ -/* if (zs_soft[channel].is_cons) { - write_zsreg(zs_soft[channel].zs_channel, R1, - (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); - write_zsreg(zs_soft[channel].zs_channel, R9, - (VIS | MIE)); - } -*/ + zs_parms->irq); } for (info = zs_chain, i = 0; info; info = info->zs_next, i++) { -#ifdef CONFIG_KGDB - if (info->kgdb_channel) { + if (info->hook && info->hook->init_info) { + (*info->hook->init_info)(info); continue; } -#endif info->magic = SERIAL_MAGIC; info->port = (int) info->zs_channel->control; info->line = i; @@ -1765,13 +1965,18 @@ info->blocked_open = 0; info->tqueue.routine = do_softint; info->tqueue.data = info; - info->callout_termios =callout_driver.init_termios; + info->callout_termios = callout_driver.init_termios; info->normal_termios = serial_driver.init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - printk("tty%02d at 0x%08x (irq = %d)", info->line, + printk("ttyS%02d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); + tty_register_devfs(&serial_driver, 0, + serial_driver.minor_start + info->line); + tty_register_devfs(&callout_driver, 0, + callout_driver.minor_start + info->line); + } restore_flags(flags); @@ -1795,38 +2000,116 @@ } /* - * ------------------------------------------------------------ - * Serial console driver - * ------------------------------------------------------------ + * polling I/O routines */ -#ifdef CONFIG_SERIAL_CONSOLE +static int +zs_poll_tx_char(struct dec_serial *info, unsigned char ch) +{ + struct dec_zschannel *chan = info->zs_channel; + int ret; + if(chan) { + int loops = 10000; +// int nine = read_zsreg(chan, R9); -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - */ + RECOVERY_DELAY; +// write_zsreg(chan, R9, nine & ~MIE); + wbflush(); + RECOVERY_DELAY; + + while (!(*(chan->control) & Tx_BUF_EMP) && --loops) + RECOVERY_DELAY; + + if (loops) { + ret = 0; + *(chan->data) = ch; + wbflush(); + RECOVERY_DELAY; + } else + ret = -EAGAIN; + +// write_zsreg(chan, R9, nine); + wbflush(); + RECOVERY_DELAY; + + return ret; + } -/* This is for console output */ -static void -zs_console_putchar(struct dec_serial *info, char ch) + return -ENODEV; +} + +static int +zs_poll_rx_char(struct dec_serial *info) { - int loops = 10000; - unsigned long flags; + struct dec_zschannel *chan = info->zs_channel; + int ret; - if(!info->zs_channel) - return; + if(chan) { + int loops = 10000; - save_flags(flags); cli(); + while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + loops--; - while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops) - RECOVERY_DELAY; - *(info->zs_channel->data) = ch; - wbflush(); RECOVERY_DELAY; + if (loops) + ret = read_zsdata(chan); + else + ret = -EAGAIN; - restore_flags(flags); + return ret; + } else + return -ENODEV; +} + +unsigned int register_zs_hook(unsigned int channel, struct zs_hook *hook) +{ + struct dec_serial *info = &zs_soft[channel]; + + if (info->hook) { + printk(__FUNCTION__": line %d has already a hook registered\n", channel); + + return 0; + } else { + info->hook = hook; + + if (zs_chain == 0) + probe_sccs(); + + if (!(info->flags & ZILOG_INITIALIZED)) + zs_startup(info); + + hook->poll_rx_char = zs_poll_rx_char; + hook->poll_tx_char = zs_poll_tx_char; + + return 1; + } +} + +unsigned int unregister_zs_hook(unsigned int channel) +{ + struct dec_serial *info = &zs_soft[channel]; + + if (info->hook) { + info->hook = NULL; + return 1; + } else { + printk(__FUNCTION__": trying to unregister hook on line %d," + " but none is registered\n", channel); + return 0; + } } +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ static void serial_console_write(struct console *co, const char *s, unsigned count) { @@ -1835,28 +2118,11 @@ info = zs_soft + co->index; -#if 0 - /* - * disable master interrupt if necessary - */ - nine = info->zs_channel->curregs[9]; - if(nine & MIE) - write_zsreg(info->zs_channel, R9, nine & ~MIE); -#endif - /* - * do it - */ for (i = 0; i < count; i++, s++) { if(*s == '\n') - zs_console_putchar(info, '\r'); - zs_console_putchar(info, *s); + zs_poll_tx_char(info, '\r'); + zs_poll_tx_char(info, *s); } - /* - * restore master interrupt enable - */ -#if 0 - write_zsreg(info->zs_channel, R9, nine); -#endif } /* @@ -1864,7 +2130,11 @@ */ static int serial_console_wait_key(struct console *co) { - return 0; + struct dec_serial *info; + + info = zs_soft + co->index; + + return zs_poll_rx_char(info); } static kdev_t serial_console_device(struct console *c) @@ -1888,7 +2158,7 @@ char *s; unsigned long flags; - if(!IOASIC) + if(!BUS_PRESENT) return -ENODEV; info = zs_soft + co->index; @@ -1963,7 +2233,7 @@ /* * Turn on RTS and DTR. */ - zs_rtsdtr(info, 1); + zs_rtsdtr(info, RTS | DTR, 1); /* * Finally, enable sequencing @@ -2017,6 +2287,18 @@ #endif /* ifdef CONFIG_SERIAL_CONSOLE */ #ifdef CONFIG_KGDB +struct dec_zschannel *zs_kgdbchan; +static unsigned char scc_inittab[] = { + 9, 0x80, /* reset A side (CHRA) */ + 13, 0, /* set baud rate divisor */ + 12, 1, + 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ + 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ + 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ + 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ + 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ +}; + /* These are for receiving and sending characters under the kgdb * source level kernel debugger. */ @@ -2051,6 +2333,25 @@ write_zsreg(chan, 1, one); write_zsreg(chan, 9, nine); } + +static int kgdbhook_init_channel(struct dec_serial* info) +{ + return 0; +} + +static void kgdbhook_init_info(struct dec_serial* info) +{ +} + +static void kgdbhook_rx_char(struct dec_serial* info, + unsigned char ch, unsigned char stat) +{ + if (ch == 0x03 || ch == '$') + breakpoint(); + if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) + write_zsreg(info->zs_channel, 0, ERR_RES); +} + /* This sets up the serial port we're using, and turns on * interrupts for that channel, so kgdb is usable once we're done. */ @@ -2059,7 +2360,7 @@ int brg; int i, x; volatile char *sccc = ms->control; - brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + brg = BPS_TO_BRG(bps, zs_parms->clock/16); printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg); for (i = 20000; i != 0; --i) { x = *sccc; eieio(); @@ -2074,6 +2375,13 @@ * for /dev/ttyb which is determined in setup_arch() from the * boot command line flags. */ +struct zs_hook zs_kgdbhook = { + init_channel : kgdbhook_init_channel, + init_info : kgdbhook_init_info, + cflags : B38400|CS8|CLOCAL, + rx_char : kgdbhook_rx_char, +} + void __init zs_kgdb_hook(int tty_num) { /* Find out how many Z8530 SCCs we have */ @@ -2084,11 +2392,12 @@ zs_soft[tty_num].change_needed = 0; zs_soft[tty_num].clk_divisor = 16; zs_soft[tty_num].zs_baud = 38400; - zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ - zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */ + zs_soft[tty_num].hook = &zs_kgdbhook; /* This runs kgdb */ /* Turn on transmitter/receiver at 8-bits/char */ kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400); printk("KGDB: on channel %d initialized\n", tty_num); set_debug_traps(); /* init stub */ } #endif /* ifdef CONFIG_KGDB */ + + diff -u --recursive --new-file v2.4.9/linux/drivers/tc/zs.h linux/drivers/tc/zs.h --- v2.4.9/linux/drivers/tc/zs.h Sat May 13 08:31:25 2000 +++ linux/drivers/tc/zs.h Mon Aug 27 08:56:31 2001 @@ -89,6 +89,18 @@ unsigned char curregs[NUM_ZSREGS]; }; +struct dec_serial; + +struct zs_hook { + int (*init_channel)(struct dec_serial* info); + void (*init_info)(struct dec_serial* info); + void (*rx_char)(unsigned char ch, unsigned char stat); + int (*poll_rx_char)(struct dec_serial* info); + int (*poll_tx_char)(struct dec_serial* info, + unsigned char ch); + unsigned cflags; +}; + struct dec_serial { struct dec_serial *zs_next; /* For IRQ servicing chain */ struct dec_zschannel *zs_channel; /* Channel registers */ @@ -97,7 +109,7 @@ char soft_carrier; /* Use soft carrier on this channel */ char break_abort; /* Is serial console in, so process brk/abrt */ - char kgdb_channel; /* Kgdb is running on this channel */ + struct zs_hook *hook; /* Hook on this channel */ char is_cons; /* Is this our console. */ unsigned char tx_active; /* character is being xmitted */ unsigned char tx_stopped; /* output is suspended */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.4.9/linux/drivers/usb/Config.in Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/Config.in Tue Aug 28 11:21:02 2001 @@ -67,7 +67,8 @@ dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL - dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB-to-USB Networking (NetChip, Prolific, ...) (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL comment 'USB port drivers' dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT diff -u --recursive --new-file v2.4.9/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.4.9/linux/drivers/usb/Makefile Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/Makefile Tue Aug 28 11:21:02 2001 @@ -65,11 +65,12 @@ obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_CATC) += catc.o +obj-$(CONFIG_USB_KAWETH) += kaweth.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_MICROTEK) += microtek.o obj-$(CONFIG_USB_BLUETOOTH) += bluetooth.o -obj-$(CONFIG_USB_NET1080) += net1080.o +obj-$(CONFIG_USB_USBNET) += usbnet.o # Object files in subdirectories diff -u --recursive --new-file v2.4.9/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.9/linux/drivers/usb/bluetooth.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/bluetooth.c Tue Aug 28 11:21:02 2001 @@ -159,7 +159,6 @@ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) #define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) -#define MIN(a,b) (((a)<(b))?(a):(b)) #define NUM_BULK_URBS 24 #define NUM_CONTROL_URBS 16 @@ -518,7 +517,7 @@ } - buffer_size = MIN (count, bluetooth->bulk_out_buffer_size); + buffer_size = min (int, count, bluetooth->bulk_out_buffer_size); memcpy (urb->transfer_buffer, current_position, buffer_size); /* build up our urb */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c --- v2.4.9/linux/drivers/usb/dc2xx.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/dc2xx.c Tue Aug 28 11:21:02 2001 @@ -63,6 +63,7 @@ #include #include #include +#include #ifdef CONFIG_USB_DEBUG #define DEBUG @@ -72,6 +73,9 @@ #include +/* /dev/usb dir. */ +extern devfs_handle_t usb_devfs_handle; + /* * Version Information */ @@ -137,11 +141,12 @@ /* this is non-null iff the device is open */ char *buf; /* buffer for I/O */ + devfs_handle_t devfs; /* devfs device */ + /* always valid */ wait_queue_head_t wait; /* for timed waits */ }; - /* Support multiple cameras, possibly of different types. */ static struct camera_state *minor_data [MAX_CAMERAS]; @@ -368,8 +373,10 @@ struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; int direction, ep; + char name[8]; struct camera_state *camera = NULL; + /* these have one config, one interface */ if (dev->descriptor.bNumConfigurations != 1 || dev->config[0].bNumInterfaces != 1) { @@ -446,6 +453,15 @@ camera->dev = dev; usb_inc_dev_use (dev); + + /* If we have devfs, register the device */ + sprintf(name, "dc2xx%d", camera->subminor); + camera->devfs = devfs_register(usb_devfs_handle, name, + DEVFS_FL_DEFAULT, USB_MAJOR, + USB_CAMERA_MINOR_BASE + camera->subminor, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP, &usb_camera_fops, NULL); + goto bye; error: @@ -464,6 +480,8 @@ down (&state_table_mutex); down (&camera->sem); + + devfs_unregister(camera->devfs); /* If camera's not opened, we can clean up right away. * Else apps see a disconnect on next I/O; the release cleans. diff -u --recursive --new-file v2.4.9/linux/drivers/usb/inode.c linux/drivers/usb/inode.c --- v2.4.9/linux/drivers/usb/inode.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/inode.c Tue Aug 28 10:56:06 2001 @@ -751,7 +751,6 @@ usb_deregister(&usbdevfs_driver); return ret; } - kern_mount(&usbdevice_fs_type); #ifdef CONFIG_PROC_FS /* create mount point for usbdevfs */ usbdir = proc_mkdir("usb", proc_bus); @@ -763,7 +762,6 @@ { usb_deregister(&usbdevfs_driver); unregister_filesystem(&usbdevice_fs_type); - kern_umount(usbdevice_fs_type.kern_mnt); #ifdef CONFIG_PROC_FS if (usbdir) remove_proc_entry("usb", proc_bus); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/kaweth.c linux/drivers/usb/kaweth.c --- v2.4.9/linux/drivers/usb/kaweth.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/kaweth.c Tue Aug 28 11:21:02 2001 @@ -248,9 +248,9 @@ dr->requesttype = requesttype; dr->request = request; - dr->value = value; - dr->index = index; - dr->length = size; + dr->value = cpu_to_le16p(&value); + dr->index = cpu_to_le16p(&index); + dr->length = cpu_to_le16p(&size); return kaweth_internal_control_msg(kaweth->dev, pipe, @@ -370,6 +370,9 @@ kaweth->firmware_buf[4] = type; kaweth->firmware_buf[5] = interrupt; + kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3], + kaweth->firmware_buf[2]); + kaweth_dbg("Downloading firmware at %x to kaweth device at %x", (int)data, (int)kaweth); @@ -476,7 +479,7 @@ int count = urb->actual_length; int count2 = urb->transfer_buffer_length; - __u16 pkt_len = *(__u16 *)kaweth->rx_buf; + __u16 pkt_len = le16_to_cpup(kaweth->rx_buf); struct sk_buff *skb; @@ -608,7 +611,7 @@ kaweth_async_set_rx_mode(kaweth); netif_stop_queue(net); - *((__u16 *)kaweth->tx_buf) = skb->len; + *((__u16 *)kaweth->tx_buf) = cpu_to_le16(skb->len); memcpy(kaweth->tx_buf + 2, skb->data, skb->len); @@ -719,8 +722,6 @@ net->trans_start = jiffies; usb_unlink_urb(kaweth->tx_urb); - - netif_wake_queue(net); } /**************************************************************** @@ -836,7 +837,7 @@ kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask); kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); - kaweth_info("MTU: %d", kaweth->configuration.segment_size); + kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", (int)kaweth->configuration.hw_addr[0], (int)kaweth->configuration.hw_addr[1], @@ -879,6 +880,10 @@ kaweth->rx_urb = usb_alloc_urb(0); kaweth->net = init_etherdev(0, 0); + if (!kaweth->net) { + kaweth_err("Error calling init_etherdev."); + return kaweth; + } memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr)); memcpy(kaweth->net->dev_addr, @@ -896,7 +901,7 @@ kaweth->net->hard_start_xmit = kaweth_start_xmit; kaweth->net->set_multicast_list = kaweth_set_rx_mode; kaweth->net->get_stats = kaweth_netdev_stats; - kaweth->net->mtu = kaweth->configuration.segment_size; + kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); memset(&kaweth->stats, 0, sizeof(kaweth->stats)); @@ -1051,4 +1056,11 @@ module_init(kaweth_init); module_exit(kaweth_exit); + + + + + + + diff -u --recursive --new-file v2.4.9/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c --- v2.4.9/linux/drivers/usb/mdc800.c Wed Jul 25 17:10:23 2001 +++ linux/drivers/usb/mdc800.c Tue Aug 28 11:21:02 2001 @@ -610,16 +610,18 @@ spin_lock (&mdc800->io_lock); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) { - mdc800->open=0; + spin_unlock(&mdc800->io_lock); usb_unlink_urb (mdc800->irq_urb); usb_unlink_urb (mdc800->write_urb); usb_unlink_urb (mdc800->download_urb); + mdc800->open=0; } else { + spin_unlock (&mdc800->io_lock); retval=-EIO; } - spin_unlock (&mdc800->io_lock); + return retval; } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/net1080.c linux/drivers/usb/net1080.c --- v2.4.9/linux/drivers/usb/net1080.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/net1080.c Wed Dec 31 16:00:00 1969 @@ -1,1128 +0,0 @@ -/* - * NetChip 1080 Driver (USB Host-to-Host Link) - * Copyright (C) 2000 by David Brownell - */ - -/* - * This talks to the NetChip 1080, which can appear in "network cables" - * and other designs. This driver interoperates with the Win32 network - * drivers from NetChip, using the NetChip reference design. - * - * The IP-over-USB protocol here may be of interest. Embedded devices - * could implement it at the cost of two bulk endpoints, and whatever - * other system resources the desired IP-based applications need. - * Some Linux palmtops could support that today. (Devices that don't - * support the TTL-driven data mangling of the net1080 chip won't need - * the header/trailer support though.) - * - * STATUS: - * - * 13-sept-2000 experimental, new - * - * This doesn't yet do any network hotplugging, and there's no matching - * ifup policy script ... it should arrange bridging with "brctl", and - * should handle static and dynamic ("pump") setups. - * - * RX/TX queue sizes currently fixed at one due to URB unlink problems. - * - * 10-oct-2000 - * usb_device_id table created. - * - * 28-oct-2000 - * misc fixes; mostly, discard more TTL-mangled rx packets. - * - * 01-nov-2000 - * usb_device_id table support added by Adam J. Richter . - * - * 08-apr-2001 gb - * Identify version on module load. - * - *-------------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG // error path messages -// #define VERBOSE // more; success messages -#define USE_TTL // timeout our reads - -#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) -# define DEBUG -#endif -#include - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.0.0" -#define DRIVER_AUTHOR "David Brownell " -#define DRIVER_DESC "NetChip 1080 Driver (USB Host-to-Host Link)" - - -static const struct usb_device_id products [] = { - // reference design - { USB_DEVICE(0x1080, 0x525), - driver_info: (unsigned long) "NetChip TurboCONNECT" }, - // Belkin, ... - { }, // END -}; - -MODULE_DEVICE_TABLE (usb, products); - -static u8 node_id [ETH_ALEN]; - - -/*------------------------------------------------------------------------- - * - * NetChip protocol: ethernet framing, and only use bulk endpoints (01/81; - * not mailboxes 02/82 or status interrupt 83). Expects Ethernet bridging. - * Odd USB length == always short read. - * - nc_header - * - payload, in Ethernet framing (14 byte header etc) - * - (optional padding byte, if needed so length is odd) - * - nc_trailer - */ - -struct nc_header { - u16 hdr_len; // sizeof nc_header (LE, all) - u16 packet_len; // packet size - u16 packet_id; // detects dropped packets -#define NC_MIN_HEADER 6 - - // all else is optional, and must start with: - // u16 vendorId; // from usb-if - // u16 productId; -}; - -#define NC_PAD_BYTE ((unsigned char)0xAC) - -struct nc_trailer { - u16 packet_id; -}; - -// packetsize == f(mtu setting), with upper limit -#define NC_MAX_PACKET(mtu) (sizeof (struct nc_header) \ - + (mtu) \ - + 1 \ - + sizeof (struct nc_trailer)) -#define MAX_PACKET 8191 - -// zero means no timeout; else, how long a 64 byte bulk -// read may be queued before HW flushes it. -#define NC_READ_TTL ((u8)255) // ms - - -/*-------------------------------------------------------------------------*/ - -// list of all devices we manage -static DECLARE_MUTEX (net1080_mutex); -static LIST_HEAD (net1080_list); - - -// Nineteen USB 1.1 max size bulk transactions per frame, max. -#if 0 -#define RX_QLEN 4 -#define TX_QLEN 4 - -#else -// unlink_urbs() has probs on OHCI without test8-pre patches. -#define RX_QLEN 1 -#define TX_QLEN 1 -#endif - -enum skb_state { - illegal = 0, - tx_start, tx_done, - rx_start, rx_done, rx_cleanup -}; - -struct skb_data { // skb->cb is one of these - struct urb *urb; - struct net1080 *dev; - enum skb_state state; - size_t length; -}; - - -struct net1080 { - // housekeeping - struct usb_device *udev; - const struct usb_device_id *prod_info; - struct semaphore mutex; - struct list_head dev_list; - wait_queue_head_t *wait; - - // protocol/interface state - struct net_device net; - struct net_device_stats stats; - u16 packet_id; - - // various kinds of pending driver work - struct sk_buff_head rxq; - struct sk_buff_head txq; - struct sk_buff_head done; - struct tasklet_struct bh; -}; - -#define mutex_lock(x) down(x) -#define mutex_unlock(x) up(x) - -static void defer_bh (struct net1080 *dev, struct sk_buff *skb) -{ - unsigned long flags; - - skb_unlink (skb); - spin_lock_irqsave (&dev->done.lock, flags); - __skb_queue_tail (&dev->done, skb); - if (dev->done.qlen == 1) - tasklet_schedule (&dev->bh); - spin_unlock_irqrestore (&dev->done.lock, flags); -} - -/*------------------------------------------------------------------------- - * - * We ignore most registers and EEPROM contents. - */ - -#define REG_USBCTL ((u8)0x04) -#define REG_TTL ((u8)0x10) -#define REG_STATUS ((u8)0x11) - -/* - * Vendor specific requests to read/write data - */ - -#define REQUEST_REGISTER ((u8)0x10) -#define REQUEST_EEPROM ((u8)0x11) - -#define CONTROL_TIMEOUT (500) /* msec */ - -static int -vendor_read (struct net1080 *dev, u8 req, u8 regnum, u16 *retval_ptr) -{ - int status = usb_control_msg (dev->udev, - usb_rcvctrlpipe (dev->udev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, regnum, - retval_ptr, sizeof *retval_ptr, - CONTROL_TIMEOUT); - if (status > 0) - status = 0; - if (!status) - le16_to_cpus (retval_ptr); - return status; -} - -static inline int -register_read (struct net1080 *dev, u8 regnum, u16 *retval_ptr) -{ - return vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr); -} - -// without retval, this can become fully async (usable in_interrupt) -static void -vendor_write (struct net1080 *dev, u8 req, u8 regnum, u16 value) -{ - usb_control_msg (dev->udev, - usb_sndctrlpipe (dev->udev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, regnum, - 0, 0, // data is in setup packet - CONTROL_TIMEOUT); -} - -static inline void -register_write (struct net1080 *dev, u8 regnum, u16 value) -{ - vendor_write (dev, REQUEST_REGISTER, regnum, value); -} - - -#if 0 -static void dump_registers (struct net1080 *dev) -{ - u8 reg; - u16 value; - - dbg ("%s registers:", dev->net.name); - for (reg = 0; reg < 0x20; reg++) { - int retval; - - // reading some registers is trouble - if (reg >= 0x08 && reg <= 0xf) - continue; - if (reg >= 0x12 && reg <= 0x1e) - continue; - - retval = register_read (dev, reg, &value); - if (retval < 0) - dbg ("%s reg [0x%x] ==> error %d", - dev->net.name, reg, retval); - else - dbg ("%s reg [0x%x] = 0x%x", - dev->net.name, reg, value); - } -} -#endif - - -/*------------------------------------------------------------------------- - * - * Control register - */ - -#define USBCTL_WRITABLE_MASK 0x1f0f -// bits 15-13 reserved, r/o -#define USBCTL_ENABLE_LANG (1 << 12) -#define USBCTL_ENABLE_MFGR (1 << 11) -#define USBCTL_ENABLE_PROD (1 << 10) -#define USBCTL_ENABLE_SERIAL (1 << 9) -#define USBCTL_ENABLE_DEFAULTS (1 << 8) -// bits 7-4 reserved, r/o -#define USBCTL_FLUSH_OTHER (1 << 3) -#define USBCTL_FLUSH_THIS (1 << 2) -#define USBCTL_DISCONN_OTHER (1 << 1) -#define USBCTL_DISCONN_THIS (1 << 0) - -#ifdef DEBUG -static void dump_usbctl (struct net1080 *dev, u16 usbctl) -{ - dbg ("%s: USB %d dev %d usbctl 0x%x:%s%s%s%s%s;" - " this%s%s;" - " other%s%s; r/o 0x%x", - dev->net.name, - dev->udev->bus->busnum, dev->udev->devnum, - usbctl, - (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", - (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", - (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", - (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", - (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", - - (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", - (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", - usbctl & ~USBCTL_WRITABLE_MASK - ); -} -#else -static inline void dump_usbctl (struct net1080 *dev, u16 usbctl) {} -#endif - -/*------------------------------------------------------------------------- - * - * Status register - */ - -#define STATUS_PORT_A (1 << 15) - -#define STATUS_CONN_OTHER (1 << 14) -#define STATUS_SUSPEND_OTHER (1 << 13) -#define STATUS_MAILBOX_OTHER (1 << 12) -#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) - -#define STATUS_CONN_THIS (1 << 6) -#define STATUS_SUSPEND_THIS (1 << 5) -#define STATUS_MAILBOX_THIS (1 << 4) -#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) - -#define STATUS_UNSPEC_MASK 0x0c8c -#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) - - -#ifdef DEBUG -static void dump_status (struct net1080 *dev, u16 status) -{ - dbg ("%s: USB %d dev %d status 0x%x:" - " this (%c) PKT=%d%s%s%s;" - " other PKT=%d%s%s%s; unspec 0x%x", - dev->net.name, - dev->udev->bus->busnum, dev->udev->devnum, - status, - - // XXX the packet counts don't seem right - // (1 at reset, not 0); maybe UNSPEC too - - (status & STATUS_PORT_A) ? 'A' : 'B', - STATUS_PACKETS_THIS (status), - (status & STATUS_CONN_THIS) ? " CON" : "", - (status & STATUS_SUSPEND_THIS) ? " SUS" : "", - (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", - - STATUS_PACKETS_OTHER (status), - (status & STATUS_CONN_OTHER) ? " CON" : "", - (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", - (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", - - status & STATUS_UNSPEC_MASK - ); -} -#else -static inline void dump_status (struct net1080 *dev, u16 status) {} -#endif - -/*------------------------------------------------------------------------- - * - * TTL register - */ - -#define TTL_THIS(ttl) (0x00ff & ttl) -#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8)) -#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this)))) - -#ifdef DEBUG -static void dump_ttl (struct net1080 *dev, u16 ttl) -{ - dbg ("%s: USB %d dev %d ttl 0x%x this = %d, other = %d", - dev->net.name, - dev->udev->bus->busnum, dev->udev->devnum, - ttl, - - TTL_THIS (ttl), - TTL_OTHER (ttl) - ); -} -#else -static inline void dump_ttl (struct net1080 *dev, u16 ttl) {} -#endif - -#define RUN_CONTEXT (in_irq () ? "in_irq" \ - : (in_interrupt () ? "in_interrupt" : "can sleep")) - -/*-------------------------------------------------------------------------*/ - -// ensure that the device is in a known state before using it. - -// preconditions: -// caller owns the device mutex -// caller has a process context - -static int net1080_reset (struct net1080 *dev) -{ - u16 usbctl, status, ttl; - int retval; - - if ((retval = register_read (dev, REG_STATUS, &status)) < 0) { - dbg ("can't read dev %d status: %d", dev->udev->devnum, retval); - goto done; - } - dump_status (dev, status); - - if ((retval = register_read (dev, REG_USBCTL, &usbctl)) < 0) { - dbg ("can't read USBCTL, %d", retval); - goto done; - } - dump_usbctl (dev, usbctl); - - register_write (dev, REG_USBCTL, - USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER); - - if ((retval = register_read (dev, REG_TTL, &ttl)) < 0) { - dbg ("can't read TTL, %d", retval); - goto done; - } - dump_ttl (dev, ttl); - -#ifdef USE_TTL - // Have the chip flush reads that seem to be starving for read - // bandwidth ... or we're otherwise reading. Note, Win32 drivers - // may change our read TTL for us. - - register_write (dev, REG_TTL, - MK_TTL (NC_READ_TTL, TTL_OTHER (ttl)) ); - dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL); -#endif - - info ("%s: %s, port %c on USB %d dev %d, peer %sconnected", - dev->net.name, (char *) dev->prod_info->driver_info, - (status & STATUS_PORT_A) ? 'A' : 'B', - dev->udev->bus->busnum, - dev->udev->devnum, - (status & STATUS_CONN_OTHER) ? "" : "dis" - ); - retval = 0; - -done: - return retval; -} - - -/*------------------------------------------------------------------------- - * - * Network Device Driver support (peer link to USB Host) - * - --------------------------------------------------------------------------*/ - -static int net1080_change_mtu (struct net_device *net, int new_mtu) -{ - if ((new_mtu < 0) || NC_MAX_PACKET (new_mtu) > MAX_PACKET) - return -EINVAL; - net->mtu = new_mtu; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct net_device_stats *net1080_get_stats (struct net_device *net) -{ - return &((struct net1080 *) net->priv)->stats; -} - -/*-------------------------------------------------------------------------*/ - -static void rx_complete (struct urb *urb); - -static void rx_submit (struct net1080 *dev, struct urb *urb, int flags) -{ - struct sk_buff *skb; - struct skb_data *entry; - int retval = 0; - unsigned long lockflags; - - if ((skb = alloc_skb (NC_MAX_PACKET (dev->net.mtu), flags)) == 0) { - err ("no rx skb"); - tasklet_schedule (&dev->bh); - usb_free_urb (urb); - return; - } - - entry = (struct skb_data *) skb->cb; - entry->urb = urb; - entry->dev = dev; - entry->state = rx_start; - entry->length = 0; - - FILL_BULK_URB (urb, dev->udev, usb_rcvbulkpipe (dev->udev, 1), - skb->data, skb->truesize, rx_complete, skb); - urb->transfer_flags |= USB_QUEUE_BULK; - - spin_lock_irqsave (&dev->rxq.lock, lockflags); - if (!netif_queue_stopped (&dev->net)) { - if ((retval = usb_submit_urb (urb)) != 0) { - err ("%s rx submit, %d", dev->net.name, retval); - tasklet_schedule (&dev->bh); - } else { - __skb_queue_tail (&dev->rxq, skb); - } - } else { - dbg ("rx: stopped"); - retval = -ENOLINK; - } - spin_unlock_irqrestore (&dev->rxq.lock, lockflags); - if (retval) { - dev_kfree_skb_any (skb); - usb_free_urb (urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static void rx_complete (struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct skb_data *entry = (struct skb_data *) skb->cb; - struct net1080 *dev = entry->dev; - int urb_status = urb->status; - - urb->dev = 0; - skb->len = urb->actual_length; - entry->state = rx_done; - entry->urb = 0; - - if ((urb->transfer_flags & USB_ASYNC_UNLINK) != 0) { - dbg ("rx ... shutting down"); - usb_free_urb (urb); - urb = 0; - } - - switch (urb_status) { - // success - case 0: - if (!(skb->len & 0x01)) { - entry->state = rx_cleanup; - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; - dbg ("even rx len %d", skb->len); - } else if (skb->len > MAX_PACKET) { - entry->state = rx_cleanup; - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; - dbg ("rx too big, %d", skb->len); - } - break; - - // hardware-reported interface shutdown ... which we - // typically see before khubd calls disconnect() - case -ETIMEDOUT: // usb-ohci - case -EILSEQ: // *uhci ... "crc"/timeout error - // netif_device_detach (&dev->net); - // FALLTHROUGH - - // software-driven interface shutdown - case -ECONNRESET: - entry->state = rx_cleanup; - usb_free_urb (urb); - urb = 0; - dbg ("%s ... shutdown rx (%d)", dev->net.name, urb_status); - break; - - // data overrun ... flush fifo? - case -EOVERFLOW: - dev->stats.rx_over_errors++; - // FALLTHROUGH - - default: - entry->state = rx_cleanup; - dev->stats.rx_errors++; - err ("%s rx: status %d", dev->net.name, urb_status); - break; - } - defer_bh (dev, skb); - - if (urb) { - if (!netif_queue_stopped (&dev->net)) { - rx_submit (dev, urb, GFP_ATOMIC); - return; - } else - usb_free_urb (urb); - } -#ifdef VERBOSE - dbg ("no read resubmitted"); -#endif /* VERBOSE */ -} - -/*-------------------------------------------------------------------------*/ - -// unlink pending rx/tx; completion handlers do all other cleanup - -static int unlink_urbs (struct sk_buff_head *q) -{ - unsigned long flags; - struct sk_buff *skb; - struct skb_data *entry; - int retval; - int count = 0; - - spin_lock_irqsave (&q->lock, flags); - for (skb = q->next; skb != (struct sk_buff *) q; skb = skb->next) { - entry = (struct skb_data *) skb->cb; - entry->urb->transfer_flags |= USB_ASYNC_UNLINK; - retval = usb_unlink_urb (entry->urb); - if (retval < 0) - dbg ("unlink urb err, %d", retval); - else - count++; - } - spin_unlock_irqrestore (&q->lock, flags); - return count; -} - - -/*-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static int net1080_stop (struct net_device *net) -{ - struct net1080 *dev = (struct net1080 *) net->priv; - int temp; - DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); - DECLARE_WAITQUEUE (wait, current); - - mutex_lock (&dev->mutex); - - dbg ("%s stop stats: rx/tx %ld/%ld, errs %ld/%ld", net->name, - dev->stats.rx_packets, dev->stats.tx_packets, - dev->stats.rx_errors, dev->stats.tx_errors - ); - - netif_stop_queue(net); - - // ensure there are no more active urbs - add_wait_queue (&unlink_wakeup, &wait); - dev->wait = &unlink_wakeup; - temp = unlink_urbs (&dev->txq) + unlink_urbs (&dev->rxq); - - // maybe wait for deletions to finish. - if (temp) { - current->state = TASK_UNINTERRUPTIBLE; - schedule (); - dbg ("waited for %d urb completions", temp); - } - dev->wait = 0; - current->state = TASK_RUNNING; - remove_wait_queue (&unlink_wakeup, &wait); - - mutex_unlock (&dev->mutex); - MOD_DEC_USE_COUNT; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -// posts a read, and enables write queing - -// precondition: never called in_interrupt - -static int net1080_open (struct net_device *net) -{ - struct net1080 *dev = (struct net1080 *) net->priv; - int retval; - u16 status; - int i; - - MOD_INC_USE_COUNT; - mutex_lock (&dev->mutex); - - // insist peer be connected -- is this the best place? - if ((retval = register_read (dev, REG_STATUS, &status)) != 0) { - dbg ("%s open: status read failed - %d", net->name, retval); - goto done; - } - if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER) { - retval = -ENOLINK; - dbg ("%s open: peer not connected", net->name); - goto done; - } - - MOD_INC_USE_COUNT; - netif_start_queue (net); - for (i = 0; i < RX_QLEN; i++) - rx_submit (dev, usb_alloc_urb (0), GFP_KERNEL); - - dbg ("%s open: started queueing (rx %d, tx %d)", - net->name, RX_QLEN, TX_QLEN); -done: - mutex_unlock (&dev->mutex); - MOD_DEC_USE_COUNT; - return retval; -} - -/*-------------------------------------------------------------------------*/ - -static void tx_complete (struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct skb_data *entry = (struct skb_data *) skb->cb; - struct net1080 *dev = entry->dev; - - urb->dev = 0; - entry->state = tx_done; - defer_bh (dev, skb); - netif_wake_queue (&dev->net); -} - -/*-------------------------------------------------------------------------*/ - -static struct sk_buff *fixup_skb (struct sk_buff *skb) -{ - int padlen; - struct sk_buff *skb2; - - padlen = ((skb->len + sizeof (struct nc_header) - + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1; - if (!skb_cloned (skb)) { - int headroom = skb_headroom (skb); - int tailroom = skb_tailroom (skb); - - if ((padlen + sizeof (struct nc_trailer)) <= tailroom - && sizeof (struct nc_header) <= headroom) - return skb; - - if ((sizeof (struct nc_header) + padlen - + sizeof (struct nc_trailer)) < - (headroom + tailroom)) { - skb->data = memmove (skb->head - + sizeof (struct nc_header), - skb->data, skb->len); - skb->tail = skb->data + skb->len; - return skb; - } - } - skb2 = skb_copy_expand (skb, - sizeof (struct nc_header), - sizeof (struct nc_trailer) + padlen, - in_interrupt () ? GFP_ATOMIC : GFP_KERNEL); - dev_kfree_skb_any (skb); - return skb2; -} - -/*-------------------------------------------------------------------------*/ - -static int net1080_start_xmit (struct sk_buff *skb, struct net_device *net) -{ - struct net1080 *dev = (struct net1080 *) net->priv; - int length = skb->len; - int retval = 0; - struct urb *urb = 0; - struct skb_data *entry; - struct nc_header *header; - struct nc_trailer *trailer; - unsigned long flags; - - if ((skb = fixup_skb (skb)) == 0) { - dbg ("can't fixup skb"); - goto drop; - } - if ((urb = usb_alloc_urb (0)) == 0) { - dbg ("no urb"); - goto drop; - } - - entry = (struct skb_data *) skb->cb; - entry->urb = urb; - entry->dev = dev; - entry->state = tx_start; - entry->length = length; - - header = (struct nc_header *) skb_push (skb, sizeof *header); - header->hdr_len = cpu_to_le16 (sizeof (*header)); - header->packet_len = cpu_to_le16 (length); - if (!((skb->len + sizeof *trailer) & 0x01)) - *skb_put (skb, 1) = NC_PAD_BYTE; - trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer); - - FILL_BULK_URB (urb, dev->udev, - usb_sndbulkpipe (dev->udev, 1), - skb->data, skb->len, tx_complete, skb); - urb->transfer_flags |= USB_QUEUE_BULK; - // FIXME urb->timeout = ...; - - spin_lock_irqsave (&dev->txq.lock, flags); - if (!netif_queue_stopped (&dev->net)) { - header->packet_id = cpu_to_le16 (dev->packet_id++); - put_unaligned (header->packet_id, &trailer->packet_id); - - netif_stop_queue (net); - if ((retval = usb_submit_urb (urb)) != 0) { - netif_start_queue (net); - dbg ("%s tx: submit urb err %d", net->name, retval); - } else { - net->trans_start = jiffies; - __skb_queue_tail (&dev->txq, skb); - if (dev->txq.qlen < TX_QLEN) - netif_start_queue (net); - } - } else - retval = -ENOLINK; - spin_unlock_irqrestore (&dev->txq.lock, flags); - - if (retval) { - dbg ("drop"); -drop: - dev->stats.tx_dropped++; - dev_kfree_skb_any (skb); - usb_free_urb (urb); -#ifdef VERBOSE - } else { - dbg ("%s: tx %p len %d", net->name, skb, length); -#endif - } - return retval; -} - - -/*-------------------------------------------------------------------------*/ - -static void rx_process (struct net1080 *dev, struct sk_buff *skb) -{ - struct nc_header *header; - struct nc_trailer *trailer; - - header = (struct nc_header *) skb->data; - le16_to_cpus (&header->hdr_len); - le16_to_cpus (&header->packet_len); - if (header->packet_len > MAX_PACKET) { - dev->stats.rx_frame_errors++; - dbg ("packet too big, %d", header->packet_len); - goto error; - } else if (header->hdr_len < NC_MIN_HEADER) { - dev->stats.rx_frame_errors++; - dbg ("header too short, %d", header->hdr_len); - goto error; - } else if (header->hdr_len > header->packet_len) { - dev->stats.rx_frame_errors++; - dbg ("header too big, %d packet %d", header->hdr_len, header->packet_len); - goto error; - } else if (header->hdr_len != sizeof *header) { - // out of band data for us? - dbg ("header OOB, %d bytes", header->hdr_len - NC_MIN_HEADER); - // switch (vendor/product ids) { ... } - } - skb_pull (skb, header->hdr_len); - - trailer = (struct nc_trailer *) - (skb->data + skb->len - sizeof *trailer); - skb_trim (skb, skb->len - sizeof *trailer); - - if ((header->packet_len & 0x01) == 0) { - if (skb->data [header->packet_len] != NC_PAD_BYTE) { - dev->stats.rx_frame_errors++; - dbg ("bad pad"); - goto error; - } - skb_trim (skb, skb->len - 1); - } - if (skb->len != header->packet_len) { - dev->stats.rx_length_errors++; - dbg ("bad packet len %d (expected %d)", - skb->len, header->packet_len); - goto error; - } - if (header->packet_id != get_unaligned (&trailer->packet_id)) { - dev->stats.rx_fifo_errors++; - dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", - header->packet_id, trailer->packet_id); - goto error; - } - - if (skb->len) { - skb->dev = &dev->net; - skb->protocol = eth_type_trans (skb, &dev->net); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - -#ifdef VERBOSE - dbg ("%s: rx %p len %d, type 0x%x, id 0x%x", - dev->net.name, skb, skb->len, skb->protocol, - le16_to_cpu (header->packet_id)); -#endif - netif_rx (skb); - } else { - dbg ("drop"); -error: - dev->stats.rx_errors++; - dev_kfree_skb (skb); - } -} - -/*-------------------------------------------------------------------------*/ - -// tasklet - -// We can have a state machine in this tasklet monitor the link state, -// using async control messaging and calling attach/detach routines. - -// But then some listener ought to respond to the changes; do those -// network attach/detach notifications get to userland somehow, such -// as by calling "ifup usb0" and "ifdown usb0"? - -static void net1080_bh (unsigned long param) -{ - struct net1080 *dev = (struct net1080 *) param; - struct sk_buff *skb; - struct skb_data *entry; - - while ((skb = skb_dequeue (&dev->done))) { - entry = (struct skb_data *) skb->cb; - switch (entry->state) { - case rx_done: - rx_process (dev, skb); - continue; - case tx_done: - if (entry->urb->status) { - // can this statistic become more specific? - dev->stats.tx_errors++; - dbg ("%s tx: err %d", dev->net.name, - entry->urb->status); - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += entry->length; - } - // FALLTHROUGH: - case rx_cleanup: - usb_free_urb (entry->urb); - dev_kfree_skb (skb); - continue; - default: - dbg ("%s: bogus skb state %d", - dev->net.name, entry->state); - } - } - - // waiting for all pending urbs to complete? - if (dev->wait) { - if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { - wake_up (dev->wait); - } - - // or are we maybe short a few urbs? - } else if (!netif_queue_stopped (&dev->net)) { - if (dev->rxq.qlen < TX_QLEN) { - struct urb *urb; - int i; - for (i = 0; i < 3 && dev->rxq.qlen < TX_QLEN; i++) { - if ((urb = usb_alloc_urb (0)) != 0) - rx_submit (dev, urb, GFP_ATOMIC); - } - dbg ("%s: rxqlen now %d", - dev->net.name, dev->rxq.qlen); - } - } -} - -/*------------------------------------------------------------------------- - * - * USB Device Driver support - * - --------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static void net1080_disconnect (struct usb_device *udev, void *ptr) -{ - struct net1080 *dev = (struct net1080 *) ptr; - - info ("%s: USB %d dev %d, %s, disconnected", - dev->net.name, - udev->bus->busnum, udev->devnum, - (char *) dev->prod_info->driver_info); - - unregister_netdev (&dev->net); - - mutex_lock (&net1080_mutex); - mutex_lock (&dev->mutex); - list_del (&dev->dev_list); - mutex_unlock (&net1080_mutex); - -#ifdef DEBUG - memset (dev, 0x55, sizeof *dev); -#endif - kfree (dev); - usb_dec_dev_use (udev); -} - - -/*-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static void * -net1080_probe (struct usb_device *udev, unsigned ifnum, const struct usb_device_id *prod) -{ - struct net1080 *dev; - struct net_device *net; - struct usb_interface_descriptor *interface; - int retval; - - // sanity check; expect dedicated interface/devices for now. - interface = &udev->actconfig->interface [ifnum].altsetting[0]; - if (udev->descriptor.bNumConfigurations != 1 - || udev->config[0].bNumInterfaces != 1 - || udev->config[0].bNumInterfaces != 1 - || interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC - || interface->bNumEndpoints != 5 - ) { - dbg ("Bogus config info"); - return 0; - } - - // set up our own records - if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) { - dbg ("can't kmalloc dev"); - return 0; - } - memset (dev, 0, sizeof *dev); - - init_MUTEX_LOCKED (&dev->mutex); - usb_inc_dev_use (udev); - dev->udev = udev; - dev->prod_info = prod; - INIT_LIST_HEAD (&dev->dev_list); - skb_queue_head_init (&dev->rxq); - skb_queue_head_init (&dev->txq); - skb_queue_head_init (&dev->done); - dev->bh.func = net1080_bh; - dev->bh.data = (unsigned long) dev; - - // set up network interface records - net = &dev->net; - net->priv = dev; - strcpy (net->name, "usb%d"); - memcpy (net->dev_addr, node_id, sizeof node_id); - - ether_setup (net); - // net->flags |= IFF_POINTOPOINT; - - net->change_mtu = net1080_change_mtu; - net->get_stats = net1080_get_stats; - net->hard_start_xmit = net1080_start_xmit; - net->open = net1080_open; - net->stop = net1080_stop; - - register_netdev (&dev->net); - - // ... talk to the device - // dump_registers (dev); - - if ((retval = net1080_reset (dev)) < 0) { - err ("%s: init reset fail on USB %d dev %d - %d", - dev->net.name, udev->bus->busnum, udev->devnum, retval); - mutex_unlock (&dev->mutex); - net1080_disconnect (udev, dev); - return 0; - } - - // ok, it's ready to go. - mutex_lock (&net1080_mutex); - list_add (&dev->dev_list, &net1080_list); - mutex_unlock (&dev->mutex); - - // start as if the link is up - netif_device_attach (&dev->net); - - mutex_unlock (&net1080_mutex); - - return dev; -} - - -/*-------------------------------------------------------------------------*/ - -static struct usb_driver net1080_driver = { - name: "net1080", - id_table: products, - probe: net1080_probe, - disconnect: net1080_disconnect, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init net1080_init (void) -{ - // compiler should optimize this out - if (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data)) - BUG (); - - if (usb_register (&net1080_driver) < 0) - return -1; - - get_random_bytes (node_id, sizeof node_id); - node_id [0] &= 0x7f; - - info(DRIVER_VERSION ":" DRIVER_DESC); - - return 0; -} -module_init (net1080_init); - -static void __exit net1080_exit (void) -{ - usb_deregister (&net1080_driver); -} -module_exit (net1080_exit); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); - diff -u --recursive --new-file v2.4.9/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.4.9/linux/drivers/usb/pegasus.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/pegasus.c Tue Aug 28 07:09:44 2001 @@ -1,7 +1,7 @@ /* ** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller ** -** Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@dce.bg) +** Copyright (c) 1999-2001 Petko Manolov (pmanolov@lnxw.com) ** ** ** ChangeLog: @@ -53,9 +53,9 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.4.19 2001/06/07 (C) 1999-2001" +#define DRIVER_VERSION "v0.4.21 (2001/08/27)" #define DRIVER_AUTHOR "Petko Manolov " -#define DRIVER_DESC "ADMtek AN986 Pegasus USB Ethernet driver" +#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define PEGASUS_USE_INTR #define PEGASUS_WRITE_EEPROM @@ -117,9 +117,7 @@ warn( __FUNCTION__ " status %d", urb->status); } pegasus->flags &= ~ETH_REGS_CHANGED; - if ( waitqueue_active(&pegasus->ctrl_wait) ) { - wake_up_interruptible( &pegasus->ctrl_wait ); - } + wake_up(&pegasus->ctrl_wait ); } @@ -135,9 +133,13 @@ return 0; } memcpy(buffer,data,size); - + + add_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); while ( pegasus->flags & ETH_REGS_CHANGED ) - interruptible_sleep_on( &pegasus->ctrl_wait ); + schedule(); + remove_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_RUNNING); pegasus->dr.requesttype = PEGASUS_REQT_READ; pegasus->dr.request = PEGASUS_REQ_GET_REGS; @@ -152,7 +154,7 @@ buffer, size, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); + set_current_state( TASK_UNINTERRUPTIBLE ); if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRLs %d", ret); @@ -182,8 +184,12 @@ } memcpy(buffer, data, size); + add_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); while ( pegasus->flags & ETH_REGS_CHANGED ) - interruptible_sleep_on( &pegasus->ctrl_wait ); + schedule(); + remove_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_RUNNING); pegasus->dr.requesttype = PEGASUS_REQT_WRITE; pegasus->dr.request = PEGASUS_REQ_SET_REGS; @@ -198,7 +204,7 @@ buffer, size, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); + set_current_state( TASK_UNINTERRUPTIBLE ); if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); @@ -228,8 +234,12 @@ } memcpy(buffer, &data, 1); + add_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); while ( pegasus->flags & ETH_REGS_CHANGED ) - interruptible_sleep_on( &pegasus->ctrl_wait ); + schedule(); + remove_wait_queue(&pegasus->ctrl_wait, &wait); + set_current_state(TASK_RUNNING); pegasus->dr.requesttype = PEGASUS_REQT_WRITE; pegasus->dr.request = PEGASUS_REQ_SET_REG; @@ -244,7 +254,7 @@ buffer, 1, ctrl_callback, pegasus ); add_wait_queue( &pegasus->ctrl_wait, &wait ); - set_current_state( TASK_INTERRUPTIBLE ); + set_current_state( TASK_UNINTERRUPTIBLE ); if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) { err( __FUNCTION__ " BAD CTRL %d", ret); @@ -620,7 +630,6 @@ } #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,48) static void pegasus_tx_timeout( struct net_device *net ) { pegasus_t *pegasus = net->priv; @@ -633,7 +642,6 @@ usb_unlink_urb( &pegasus->tx_urb ); pegasus->stats.tx_errors++; } -#endif static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net ) @@ -861,10 +869,8 @@ net->priv = pegasus; net->open = pegasus_open; net->stop = pegasus_close; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,48) net->watchdog_timeo = PEGASUS_TX_TIMEOUT; net->tx_timeout = pegasus_tx_timeout; -#endif net->do_ioctl = pegasus_ioctl; net->hard_start_xmit = pegasus_start_xmit; net->set_multicast_list = pegasus_set_multicast; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.9/linux/drivers/usb/printer.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/printer.c Tue Aug 28 11:21:02 2001 @@ -230,7 +230,7 @@ goto out; } #else - retval = 0; + retval = 0; #endif usblp->used = 1; @@ -242,7 +242,11 @@ if (usblp->bidir) { usblp->readcount = 0; usblp->readurb.dev = usblp->dev; - usb_submit_urb(&usblp->readurb); + if (usb_submit_urb(&usblp->readurb) < 0) { + retval = -EIO; + usblp->used = 0; + file->private_data = NULL; + } } out: unlock_kernel(); @@ -299,7 +303,7 @@ } if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ - + switch (_IOC_NR(cmd)) { case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ @@ -658,7 +662,7 @@ #endif sprintf(name, "lp%d", minor); - + /* if we have devfs, create with perms=660 */ usblp->devfs = devfs_register(usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR, @@ -681,8 +685,11 @@ BUG (); } + down (&usblp->sem); + lock_kernel(); usblp->dev = NULL; + unlock_kernel(); usb_unlink_urb(&usblp->writeurb); if (usblp->bidir) diff -u --recursive --new-file v2.4.9/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c --- v2.4.9/linux/drivers/usb/rio500.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/rio500.c Tue Aug 28 11:21:02 2001 @@ -120,13 +120,17 @@ unsigned char *buffer; int result, requesttype; int retries; - int retval; + int retval=0; + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) - return -1; + { + retval = -ENODEV; + goto err_out; + } switch (cmd) { case RIO_RECV_COMMAND: @@ -142,8 +146,10 @@ goto err_out; } buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; + if (buffer == NULL) { + retval = -ENOMEM; + goto err_out; + } if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { retval = -EFAULT; free_page((unsigned long) buffer); @@ -158,7 +164,6 @@ rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; - down(&(rio->lock)); while (retries) { result = usb_control_msg(rio->rio_dev, usb_rcvctrlpipe(rio-> rio_dev, 0), @@ -180,7 +185,6 @@ le32_to_cpu(*((long *) buffer))); if (copy_to_user(rio_cmd.buffer, buffer, rio_cmd.length)) { - up(&(rio->lock)); free_page((unsigned long) buffer); retval = -EFAULT; goto err_out; @@ -196,7 +200,6 @@ be swapped at the app level */ } - up(&(rio->lock)); free_page((unsigned long) buffer); break; @@ -204,16 +207,23 @@ data = (void *) arg; if (data == NULL) break; - if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) - return -EFAULT; - if (rio_cmd.length > PAGE_SIZE) - return -EINVAL; + if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) { + retval = -EFAULT; + goto err_out; + } + if (rio_cmd.length > PAGE_SIZE) { + retval = -EINVAL; + goto err_out; + } buffer = (unsigned char *) __get_free_page(GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; + if (buffer == NULL) { + retval = -ENOMEM; + goto err_out; + } if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) { free_page((unsigned long)buffer); - return -EFAULT; + retval = -EFAULT; + goto err_out; } requesttype = rio_cmd.requesttype | USB_DIR_OUT | @@ -223,7 +233,6 @@ rio_cmd.index, rio_cmd.length); /* Send rio control message */ retries = 3; - down(&(rio->lock)); while (retries) { result = usb_control_msg(rio->rio_dev, usb_sndctrlpipe(rio-> rio_dev, 0), @@ -247,16 +256,14 @@ } } - up(&(rio->lock)); free_page((unsigned long) buffer); break; default: - return -ENOIOCTLCMD; + retval = -ENOTTY; break; } - return 0; err_out: up(&(rio->lock)); @@ -277,13 +284,17 @@ int maxretry; int errn = 0; + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) - return -1; + { + up(&(rio->lock)); + return -ENODEV; + } + - down(&(rio->lock)); do { unsigned long thistime; @@ -356,17 +367,20 @@ int maxretry = 10; char *ibuf; - /* Sanity check to make sure rio is connected, powered, etc */ + down(&(rio->lock)); + /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) - return -1; + { + up(&(rio->lock)); + return -ENODEV; + } ibuf = rio->ibuf; read_count = 0; - down(&(rio->lock)); while (count > 0) { if (signal_pending(current)) { @@ -461,7 +475,7 @@ S_IWGRP, &usb_rio_fops, NULL); if (rio->devfs == NULL) dbg("probe_rio: device node registration failed"); - + init_MUTEX(&(rio->lock)); return rio; @@ -473,10 +487,12 @@ devfs_unregister(rio->devfs); + down(&(rio->lock)); if (rio->isopen) { rio->isopen = 0; /* better let it finish - the release will do whats needed */ rio->rio_dev = NULL; + up(&(rio->lock)); return; } kfree(rio->ibuf); @@ -485,6 +501,7 @@ info("USB Rio disconnected."); rio->present = 0; + up(&(rio->lock)); } static struct usb_device_id rio_table [] = { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in --- v2.4.9/linux/drivers/usb/serial/Config.in Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/Config.in Tue Aug 28 11:21:02 2001 @@ -15,7 +15,7 @@ dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL - dep_tristate ' USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL + dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL dep_tristate ' USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c --- v2.4.9/linux/drivers/usb/serial/belkin_sa.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/belkin_sa.c Tue Aug 28 11:21:02 2001 @@ -551,7 +551,8 @@ case TIOCMSET: /* Turns on and off the lines as specified by the mask */ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (get_user(mask, (unsigned long *) arg)) + return -EFAULT; if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { /* RTS needs set */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/cyberjack.c linux/drivers/usb/serial/cyberjack.c --- v2.4.9/linux/drivers/usb/serial/cyberjack.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/cyberjack.c Tue Aug 28 11:21:02 2001 @@ -241,7 +241,8 @@ /* Copy data */ if (from_user) { - copy_from_user(priv->wrbuf+priv->wrfilled, buf, count); + if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) + return -EFAULT; } else { memcpy (priv->wrbuf+priv->wrfilled, buf, count); } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.9/linux/drivers/usb/serial/digi_acceleport.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/digi_acceleport.c Tue Aug 28 11:21:02 2001 @@ -409,11 +409,6 @@ #define DIGI_READ_INPUT_SIGNALS_DCD 128 -/* macros */ -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define MIN(a,b) (((a)<(b))?(a):(b)) - - /* Structures */ typedef struct digi_serial { @@ -675,7 +670,7 @@ } /* len must be a multiple of 4, so commands are not split */ - len = MIN( count, oob_port->bulk_out_size ); + len = min(int, count, oob_port->bulk_out_size ); if( len > 4 ) len &= ~3; @@ -752,7 +747,7 @@ /* len must be a multiple of 4 and small enough to */ /* guarantee the write will send buffered data first, */ /* so commands are in order with data and not split */ - len = MIN( count, port->bulk_out_size-2-priv->dp_out_buf_len ); + len = min(int, count, port->bulk_out_size-2-priv->dp_out_buf_len ); if( len > 4 ) len &= ~3; @@ -956,7 +951,7 @@ spin_lock_irqsave( &priv->dp_port_lock, flags ); /* send any buffered chars from throttle time on to tty subsystem */ - len = MIN( priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count ); + len = min(int, priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count ); if( len > 0 ) { memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len ); memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len ); @@ -1277,7 +1272,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); /* copy user data (which can sleep) before getting spin lock */ - count = MIN( 64, MIN( count, port->bulk_out_size-2 ) ); + count = min(int, 64, min(int, count, port->bulk_out_size-2 ) ); if( from_user && copy_from_user( user_buf, buf, count ) ) { return( -EFAULT ); } @@ -1308,7 +1303,7 @@ /* allow space for any buffered data and for new data, up to */ /* transfer buffer size - 2 (for command and length bytes) */ - new_len = MIN( count, port->bulk_out_size-2-priv->dp_out_buf_len ); + new_len = min(int, count, port->bulk_out_size-2-priv->dp_out_buf_len ); data_len = new_len + priv->dp_out_buf_len; if( data_len == 0 ) { @@ -1934,7 +1929,7 @@ if( throttled ) { - len = MIN( len, + len = min( int, len, DIGI_IN_BUF_SIZE - priv->dp_in_buf_len ); if( len > 0 ) { @@ -1947,7 +1942,7 @@ } else { - len = MIN( len, TTY_FLIPBUF_SIZE - tty->flip.count ); + len = min( int, len, TTY_FLIPBUF_SIZE - tty->flip.count ); if( len > 0 ) { memcpy( tty->flip.char_buf_ptr, data, len ); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c --- v2.4.9/linux/drivers/usb/serial/empeg.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/serial/empeg.c Tue Aug 28 11:21:02 2001 @@ -85,8 +85,6 @@ #define EMPEG_VENDOR_ID 0x084f #define EMPEG_PRODUCT_ID 0x0001 -#define MIN(a,b) (((a)<(b))?(a):(b)) - /* function prototypes for an empeg-car player */ static int empeg_open (struct usb_serial_port *port, struct file *filp); static void empeg_close (struct usb_serial_port *port, struct file *filp); @@ -278,10 +276,13 @@ } } - transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE); + transfer_size = min (int, count, URB_TRANSFER_BUFFER_SIZE); if (from_user) { - copy_from_user (urb->transfer_buffer, current_position, transfer_size); + if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) { + bytes_sent = -EFAULT; + break; + } } else { memcpy (urb->transfer_buffer, current_position, transfer_size); } @@ -301,8 +302,11 @@ /* send it down the pipe */ status = usb_submit_urb(urb); - if (status) - dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + if (status) { + err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + bytes_sent = status; + break; + } current_position += transfer_size; bytes_sent += transfer_size; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.4.9/linux/drivers/usb/serial/ftdi_sio.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/ftdi_sio.c Tue Aug 28 11:21:02 2001 @@ -470,8 +470,9 @@ /* Copy in the data to send */ if (from_user) { - copy_from_user(port->write_urb->transfer_buffer + data_offset , - buf, count - data_offset ); + if (copy_from_user(port->write_urb->transfer_buffer + data_offset, + buf, count - data_offset )) + return -EFAULT; } else { memcpy(port->write_urb->transfer_buffer + data_offset, diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c --- v2.4.9/linux/drivers/usb/serial/io_edgeport.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/io_edgeport.c Tue Aug 28 11:21:02 2001 @@ -236,7 +236,7 @@ #include #include #include -#include +#include #include #include #include @@ -1311,7 +1311,7 @@ fifo = &edge_port->txfifo; // calculate number of bytes to put in fifo - copySize = MIN(count, (edge_port->txCredits - fifo->count)); + copySize = min (int, count, (edge_port->txCredits - fifo->count)); dbg(__FUNCTION__"(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", port->number, count, edge_port->txCredits - fifo->count, copySize); @@ -1329,12 +1329,13 @@ // then copy the reset from the start of the buffer bytesleft = fifo->size - fifo->head; - firsthalf = MIN(bytesleft,copySize); + firsthalf = min (int, bytesleft, copySize); dbg (__FUNCTION__" - copy %d bytes of %d into fifo ", firsthalf, bytesleft); /* now copy our data */ if (from_user) { - copy_from_user(&fifo->fifo[fifo->head], data, firsthalf); + if (copy_from_user(&fifo->fifo[fifo->head], data, firsthalf)) + return -EFAULT; } else { memcpy(&fifo->fifo[fifo->head], data, firsthalf); } @@ -1353,7 +1354,8 @@ if (secondhalf) { dbg (__FUNCTION__" - copy rest of data %d", secondhalf); if (from_user) { - copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); + if (copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf)) + return -EFAULT; } else { memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); } @@ -1452,7 +1454,7 @@ /* now copy our data */ bytesleft = fifo->size - fifo->tail; - firsthalf = MIN(bytesleft,count); + firsthalf = min (int, bytesleft, count); memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf); fifo->tail += firsthalf; fifo->count -= firsthalf; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/io_edgeport.h linux/drivers/usb/serial/io_edgeport.h --- v2.4.9/linux/drivers/usb/serial/io_edgeport.h Mon Mar 19 17:21:54 2001 +++ linux/drivers/usb/serial/io_edgeport.h Tue Aug 28 11:21:02 2001 @@ -25,16 +25,6 @@ #ifndef FALSE #define FALSE (0) #endif -#ifndef MIN - #define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#ifndef MAX - #define MAX(a,b) (((a)>(b))?(a):(b)) -#endif -#ifndef max - #define max MAX -#endif - #ifndef LOW8 #define LOW8(a) ((unsigned char)(a & 0xff)) #endif diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.9/linux/drivers/usb/serial/keyspan.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/keyspan.c Tue Aug 28 11:21:02 2001 @@ -349,7 +349,8 @@ ((char *)this_urb->transfer_buffer)[0] = 0; if (from_user) { - copy_from_user(this_urb->transfer_buffer + 1, buf, todo); + if (copy_from_user(this_urb->transfer_buffer + 1, buf, todo)) + return -EFAULT; } else { memcpy (this_urb->transfer_buffer + 1, buf, todo); } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c --- v2.4.9/linux/drivers/usb/serial/mct_u232.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/mct_u232.c Tue Aug 28 11:21:02 2001 @@ -94,7 +94,7 @@ */ #undef FIX_WRITE_RETURN_CODE_PROBLEM #ifdef FIX_WRITE_RETURN_CODE_PROBLEM -static int write_blocking = 0; /* disabled by default */ +static int write_blocking; /* disabled by default */ #endif /* @@ -524,7 +524,10 @@ usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf); if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, size); + if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { + up (&port->sem); + return -EFAULT; + } } else { memcpy (port->write_urb->transfer_buffer, buf, size); @@ -815,7 +818,7 @@ { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; - int ret, mask; + int mask; dbg (__FUNCTION__ "cmd=0x%x", cmd); @@ -828,7 +831,8 @@ case TIOCMSET: /* Turns on and off the lines as specified by the mask */ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (get_user(mask, (unsigned long *) arg)) + return -EFAULT; if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { /* RTS needs set */ diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.4.9/linux/drivers/usb/serial/usbserial.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/serial/usbserial.c Tue Aug 28 11:21:02 2001 @@ -307,8 +307,6 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/" #define DRIVER_DESC "USB Serial Driver core" -#define MAX(a,b) (((a)>(b))?(a):(b)) - /* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */ /* need to always compile these in, as some of the other devices use these functions as their own. */ /* if a driver does not provide a function pointer, the generic function will be called. */ @@ -852,7 +850,8 @@ count = (count > port->bulk_out_size) ? port->bulk_out_size : count; if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, count); + if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) + return -EFAULT; } else { memcpy (port->write_urb->transfer_buffer, buf, count); @@ -1260,9 +1259,9 @@ /* initialize some parts of the port structures */ /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ - max_endpoints = MAX(num_bulk_in, num_bulk_out); - max_endpoints = MAX(max_endpoints, num_interrupt_in); - max_endpoints = MAX(max_endpoints, serial->num_ports); + max_endpoints = max(int, num_bulk_in, num_bulk_out); + max_endpoints = max(int, max_endpoints, num_interrupt_in); + max_endpoints = max(int, max_endpoints, serial->num_ports); dbg (__FUNCTION__ " - setting up %d port structures for this device", max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = &serial->port[i]; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.9/linux/drivers/usb/serial/visor.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/visor.c Tue Aug 28 11:21:02 2001 @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (08/23/2001) gkh + * fixed a few potential bugs pointed out by Oliver Neukum. + * * (05/30/2001) gkh * switched from using spinlock to a semaphore, which fixes lots of problems. * @@ -115,12 +118,10 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.2" +#define DRIVER_VERSION "v1.3" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "USB HandSpring Visor driver" -#define MIN(a,b) (((a)<(b))?(a):(b)) - /* function prototypes for a handspring visor */ static int visor_open (struct usb_serial_port *port, struct file *filp); static void visor_close (struct usb_serial_port *port, struct file *filp); @@ -152,11 +153,16 @@ { } /* Terminating entry */ }; +static __devinitdata struct usb_device_id clie_id_table [] = { + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_ID) }, + { } /* Terminating entry */ +}; static __devinitdata struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_ID) }, { } /* Terminating entry */ }; @@ -242,6 +248,31 @@ read_bulk_callback: visor_read_bulk_callback, }; +/* device info for the Sony Clie */ +static struct usb_serial_device_type clie_device = { + name: "Sony Clie", + id_table: clie_id_table, + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: visor_open, + close: visor_close, + throttle: visor_throttle, + unthrottle: visor_unthrottle, + shutdown: visor_shutdown, + ioctl: visor_ioctl, + set_termios: visor_set_termios, + write: visor_write, + write_room: visor_write_room, + chars_in_buffer: visor_chars_in_buffer, + write_bulk_callback: visor_write_bulk_callback, + read_bulk_callback: visor_read_bulk_callback, +}; + #define NUM_URBS 24 #define URB_TRANSFER_BUFFER_SIZE 768 static struct urb *write_urb_pool[NUM_URBS]; @@ -351,8 +382,6 @@ dbg(__FUNCTION__ " - port %d", port->number); - usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf); - while (count > 0) { /* try to find a free urb in our list of them */ urb = NULL; @@ -376,12 +405,18 @@ } } - transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE); - if (from_user) - copy_from_user (urb->transfer_buffer, current_position, transfer_size); - else + transfer_size = min (int, count, URB_TRANSFER_BUFFER_SIZE); + if (from_user) { + if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) { + bytes_sent = -EFAULT; + break; + } + } else { memcpy (urb->transfer_buffer, current_position, transfer_size); - + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, urb->transfer_buffer); + /* build up our urb */ FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), urb->transfer_buffer, transfer_size, visor_write_bulk_callback, port); @@ -389,8 +424,11 @@ /* send it down the pipe */ status = usb_submit_urb(urb); - if (status) - dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + if (status) { + err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + bytes_sent = status; + break; + } current_position += transfer_size; bytes_sent += transfer_size; @@ -674,10 +712,16 @@ /* This function is all nice and good, but we don't change anything based on it :) */ static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) { - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag; dbg(__FUNCTION__ " - port %d", port->number); + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + return; + } + + cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && @@ -687,11 +731,6 @@ } } - if ((!port->tty) || (!port->tty->termios)) { - dbg(__FUNCTION__" - no tty structures"); - return; - } - /* get the byte size */ switch (cflag & CSIZE) { case CS5: dbg(__FUNCTION__ " - data bits = 5"); break; @@ -744,6 +783,7 @@ usb_serial_register (&handspring_device); usb_serial_register (&palm_m500_device); usb_serial_register (&palm_m505_device); + usb_serial_register (&clie_device); /* create our write urb pool and transfer buffers */ spin_lock_init (&write_urb_pool_lock); @@ -763,7 +803,7 @@ } } - info(DRIVER_VERSION ":" DRIVER_DESC); + info(DRIVER_DESC " " DRIVER_VERSION); return 0; } @@ -777,6 +817,7 @@ usb_serial_deregister (&handspring_device); usb_serial_deregister (&palm_m500_device); usb_serial_deregister (&palm_m505_device); + usb_serial_deregister (&clie_device); spin_lock_irqsave (&write_urb_pool_lock, flags); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/visor.h linux/drivers/usb/serial/visor.h --- v2.4.9/linux/drivers/usb/serial/visor.h Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/visor.h Tue Aug 28 11:21:02 2001 @@ -24,6 +24,10 @@ #define PALM_M500_ID 0x0001 #define PALM_M505_ID 0x0002 +#define SONY_VENDOR_ID 0x054C +#define SONY_CLIE_ID 0x0038 +#define SONY_CLIE_320_ID 0x0066 + /**************************************************************************** * Handspring Visor Vendor specific request codes (bRequest values) * A big thank you to Handspring for providing the following information. diff -u --recursive --new-file v2.4.9/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.4.9/linux/drivers/usb/serial/whiteheat.c Tue Jul 3 17:08:21 2001 +++ linux/drivers/usb/serial/whiteheat.c Tue Aug 28 11:21:02 2001 @@ -412,12 +412,19 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) { - unsigned int cflag = port->tty->termios->c_cflag; + unsigned int cflag; struct whiteheat_port_settings port_settings; dbg(__FUNCTION__ " -port %d", port->number); down (&port->sem); + + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + goto exit; + } + + cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { if ((cflag == old_termios->c_cflag) && @@ -427,11 +434,6 @@ } } - if ((!port->tty) || (!port->tty->termios)) { - dbg(__FUNCTION__" - no tty structures"); - goto exit; - } - /* set the port number */ /* firmware uses 1 based port numbering */ port_settings.port = port->number + 1; diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-skeleton.c linux/drivers/usb/usb-skeleton.c --- v2.4.9/linux/drivers/usb/usb-skeleton.c Wed Jul 25 17:10:24 2001 +++ linux/drivers/usb/usb-skeleton.c Tue Aug 28 11:21:02 2001 @@ -1,5 +1,5 @@ /* - * USB Skeleton driver + * USB Skeleton driver - 0.4 * * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) * @@ -22,6 +22,7 @@ * * History: * + * 2001_08_21 - 0.4 - more small bug fixes. * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people * 2001_05_01 - 0.1 - first version @@ -56,7 +57,7 @@ /* Version Information */ -#define DRIVER_VERSION "v0.3" +#define DRIVER_VERSION "v0.4" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" #define DRIVER_DESC "USB Skeleton Driver" @@ -179,6 +180,22 @@ /** + * skel_delete + */ +static inline void skel_delete (struct usb_skel *dev) +{ + minor_table[dev->minor] = NULL; + if (dev->bulk_in_buffer != NULL) + kfree (dev->bulk_in_buffer); + if (dev->bulk_out_buffer != NULL) + kfree (dev->bulk_out_buffer); + if (dev->write_urb != NULL) + usb_free_urb (dev->write_urb); + kfree (dev); +} + + +/** * skel_open */ static int skel_open (struct inode *inode, struct file *file) @@ -256,27 +273,21 @@ if (dev->udev == NULL) { /* the device was unplugged before the file was released */ - minor_table[dev->minor] = NULL; - if (dev->bulk_in_buffer != NULL) - kfree (dev->bulk_in_buffer); - if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); - kfree (dev); - goto exit; + up (&dev->sem); + skel_delete (dev); + MOD_DEC_USE_COUNT; + up (&minor_table_mutex); + return 0; } /* decrement our usage count for the device */ --dev->open_count; if (dev->open_count <= 0) { /* shutdown any bulk writes that might be going on */ - dev->write_urb->transfer_flags |= USB_ASYNC_UNLINK; usb_unlink_urb (dev->write_urb); dev->open_count = 0; } -exit: /* decrement our usage count for the module */ MOD_DEC_USE_COUNT; @@ -453,9 +464,12 @@ } - - - +/** + * skel_probe + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_skel *dev = NULL; @@ -476,7 +490,7 @@ /* select a "subminor" number (part of a minor number) */ down (&minor_table_mutex); - for (minor = 0; minor < MAX_DEVICES; i++) { + for (minor = 0; minor < MAX_DEVICES; ++minor) { if (minor_table[minor] == NULL) break; } @@ -558,14 +572,7 @@ goto exit; error: - minor_table [dev->minor] = NULL; - if (dev->bulk_in_buffer != NULL) - kfree (dev->bulk_in_buffer); - if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); - kfree (dev); + skel_delete (dev); dev = NULL; exit: @@ -576,6 +583,8 @@ /** * skel_disconnect + * + * Called by the usb core when the device is removed from the system. */ static void skel_disconnect(struct usb_device *udev, void *ptr) { @@ -591,14 +600,7 @@ /* if the device is not opened, then we clean up right now */ if (!dev->open_count) { - minor_table[dev->minor] = NULL; - if (dev->bulk_in_buffer != NULL) - kfree (dev->bulk_in_buffer); - if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); - if (dev->write_urb != NULL) - usb_free_urb (dev->write_urb); - kfree (dev); + skel_delete (dev); } else { dev->udev = NULL; up (&dev->sem); @@ -628,8 +630,7 @@ return -1; } - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); + info(DRIVER_DESC " " DRIVER_VERSION); return 0; } diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.4.9/linux/drivers/usb/usb-uhci.c Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/usb-uhci.c Tue Aug 28 11:21:02 2001 @@ -1,7 +1,7 @@ /* * Universal Host Controller Interface driver for USB (take II). * - * (c) 1999-2000 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar) * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) @@ -16,7 +16,7 @@ * (C) Copyright 1999 Randy Dunlap * (C) Copyright 1999 Gregory P. Smith * - * $Id: usb-uhci.c,v 1.259 2001/03/30 14:51:59 acher Exp $ + * $Id: usb-uhci.c,v 1.267 2001/08/28 16:45:00 acher Exp $ */ #include @@ -52,7 +52,7 @@ /* This enables an extra UHCI slab for memory debugging */ #define DEBUG_SLAB -#define VERSTR "$Revision: 1.259 $ time " __TIME__ " " __DATE__ +#define VERSTR "$Revision: 1.267 $ time " __TIME__ " " __DATE__ #include #include "usb-uhci.h" @@ -61,7 +61,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.251" +#define DRIVER_VERSION "v1.267" #define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" #define DRIVER_DESC "USB Universal Host Controller Interface driver" @@ -88,13 +88,34 @@ #define SLAB_FLAG (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL) #define KMALLOC_FLAG (in_interrupt ()? GFP_ATOMIC : GFP_KERNEL) +/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth + * Reclamation: feature that puts loop on descriptor loop when + * there's some transfer going on. With FSBR, USB performance + * is optimal, but PCI can be slowed down up-to 5 times, slowing down + * system performance (eg. framebuffer devices). + */ #define CONFIG_USB_UHCI_HIGH_BANDWIDTH + +/* *_DEPTH_FIRST puts descriptor in depth-first mode. This has + * somehow similar effect to FSBR (higher speed), but does not + * slow PCI down. OTOH USB performace is slightly slower than + * in FSBR case and single device could hog whole USB, starving + * other devices. + */ #define USE_CTRL_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first #define USE_BULK_DEPTH_FIRST 0 // 0: Breadth first, 1: Depth first +/* Turning off both CONFIG_USB_UHCI_HIGH_BANDWITH and *_DEPTH_FIRST + * will lead to <64KB/sec performance over USB for bulk transfers targeting + * one device's endpoint. You probably do not want to do that. + */ + // stop bandwidth reclamation after (roughly) 50ms #define IDLE_TIMEOUT (HZ/20) +// Suppress HC interrupt error messages for 5s +#define ERROR_SUPPRESSION_TIME (HZ*5) + _static int rh_submit_urb (urb_t *urb); _static int rh_unlink_urb (urb_t *urb); _static int delete_qh (uhci_t *s, uhci_desc_t *qh); @@ -133,20 +154,15 @@ _static void uhci_switch_timer_int(uhci_t *s) { - if (!list_empty(&s->urb_unlinked)) { - s->td1ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC); - } - else { - s->td1ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); - } - - if (s->timeout_urbs) { - s->td32ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC); - } - else { - s->td32ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); - } + if (!list_empty(&s->urb_unlinked)) + set_td_ioc(s->td1ms); + else + clr_td_ioc(s->td1ms); + if (s->timeout_urbs) + set_td_ioc(s->td32ms); + else + clr_td_ioc(s->td32ms); wmb(); } /*-------------------------------------------------------------------*/ @@ -199,6 +215,7 @@ enable_desc_loop(s, urb); } #endif + urb->status = -EINPROGRESS; ((urb_priv_t*)urb->hcpriv)->started=jiffies; list_add (p, &s->urb_list); if (urb->timeout) @@ -241,7 +258,7 @@ return -ENOMEM; memset (*new, 0, sizeof (uhci_desc_t)); (*new)->dma_addr = dma_handle; - (*new)->hw.td.link = cpu_to_le32(UHCI_PTR_TERM | (flags & UHCI_PTR_BITS)); // last by default + set_td_link((*new), UHCI_PTR_TERM | (flags & UHCI_PTR_BITS)); // last by default (*new)->type = TD_TYPE; mb(); INIT_LIST_HEAD (&(*new)->vertical); @@ -257,7 +274,7 @@ spin_lock_irqsave (&s->td_lock, xxx); - td->hw.td.link = cpu_to_le32(qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH); + set_td_link(td, qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH); mb(); spin_unlock_irqrestore (&s->td_lock, xxx); @@ -277,11 +294,11 @@ if (qh == prev ) { // virgin qh without any tds - qh->hw.qh.element = cpu_to_le32(new->dma_addr | UHCI_PTR_TERM); + set_qh_element(qh, new->dma_addr | UHCI_PTR_TERM); } else { // already tds inserted, implicitely remove TERM bit of prev - prev->hw.td.link = cpu_to_le32(new->dma_addr | (flags & UHCI_PTR_DEPTH)); + set_td_link(prev, new->dma_addr | (flags & UHCI_PTR_DEPTH)); } mb(); spin_unlock_irqrestore (&s->td_lock, xxx); @@ -300,7 +317,7 @@ next = list_entry (td->horizontal.next, uhci_desc_t, horizontal); list_add (&new->horizontal, &td->horizontal); new->hw.td.link = td->hw.td.link; - td->hw.td.link = cpu_to_le32(new->dma_addr); + set_td_link(td, new->dma_addr); mb(); spin_unlock_irqrestore (&s->td_lock, flags); @@ -361,8 +378,8 @@ return -ENOMEM; memset (*new, 0, sizeof (uhci_desc_t)); (*new)->dma_addr = dma_handle; - (*new)->hw.qh.head = cpu_to_le32(UHCI_PTR_TERM); - (*new)->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM); + set_qh_head(*new, UHCI_PTR_TERM); + set_qh_element(*new, UHCI_PTR_TERM); (*new)->type = QH_TYPE; mb(); @@ -387,16 +404,16 @@ // (OLD) (POS) -> (OLD) (NEW) (POS) old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal); list_add_tail (&new->horizontal, &pos->horizontal); - new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (pos)) ; + set_qh_head(new, MAKE_QH_ADDR (pos)) ; if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM))) - old->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ; + set_qh_head(old, MAKE_QH_ADDR (new)) ; } else { // (POS) (OLD) -> (POS) (NEW) (OLD) old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal); list_add (&new->horizontal, &pos->horizontal); - new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (old)); - pos->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ; + set_qh_head(new, MAKE_QH_ADDR (old)); + set_qh_head(pos, MAKE_QH_ADDR (new)) ; } mb (); @@ -522,7 +539,7 @@ if (s->ls_control_chain) delete_desc (s, s->ls_control_chain); if (s->control_chain) - delete_desc(s, s->control_chain); + delete_desc (s, s->control_chain); if (s->bulk_chain) delete_desc (s, s->bulk_chain); if (s->chain_end) @@ -576,24 +593,20 @@ dbg("allocating iso descs"); for (n = 0; n < 1024; n++) { // allocate skeleton iso/irq-tds - ret = alloc_td (s, &td, 0); - if (ret) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; + s->iso_td[n] = td; s->framelist[n] = cpu_to_le32((__u32) td->dma_addr); } dbg("allocating qh: chain_end"); - ret = alloc_qh (s, &qh); - - if (ret) + if (alloc_qh (s, &qh)) goto init_skel_cleanup; s->chain_end = qh; - ret = alloc_td (s, &td, 0); - - if (ret) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand) @@ -602,8 +615,7 @@ s->td1ms=td; dbg("allocating qh: bulk_chain"); - ret = alloc_qh (s, &qh); - if (ret) + if (alloc_qh (s, &qh)) goto init_skel_cleanup; insert_qh (s, s->chain_end, qh, 0); @@ -619,12 +631,11 @@ #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH // disabled reclamation loop - s->chain_end->hw.qh.head = cpu_to_le32(s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM); + set_qh_head(s->chain_end, s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM); #endif dbg("allocating qh: ls_control_chain"); - ret = alloc_qh (s, &qh); - if (ret) + if (alloc_qh (s, &qh)) goto init_skel_cleanup; insert_qh (s, s->control_chain, qh, 0); @@ -638,15 +649,15 @@ for (n = 0; n < 8; n++) { uhci_desc_t *td; - alloc_td (s, &td, 0); - if (!td) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; + s->int_chain[n] = td; if (n == 0) { - s->int_chain[0]->hw.td.link = cpu_to_le32(s->ls_control_chain->dma_addr | UHCI_PTR_QH); + set_td_link(s->int_chain[0], s->ls_control_chain->dma_addr | UHCI_PTR_QH); } else { - s->int_chain[n]->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr); + set_td_link(s->int_chain[n], s->int_chain[0]->dma_addr); } } @@ -661,16 +672,13 @@ else for (o = 1, m = 2; m <= 128; o++, m += m) if ((n & (m - 1)) == ((m - 1) / 2)) - ((uhci_desc_t*) s->iso_td[n])->hw.td.link = - cpu_to_le32(s->int_chain[o]->dma_addr); + set_td_link(((uhci_desc_t*) s->iso_td[n]), s->int_chain[o]->dma_addr); } - ret = alloc_td (s, &td, 0); - - if (ret) + if (alloc_td (s, &td, 0)) goto init_skel_cleanup; - fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt + fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt (activated later) s->td32ms=td; insert_td_horizontal (s, s->int_chain[5], td); @@ -700,20 +708,12 @@ char *data; int depth_first=USE_CTRL_DEPTH_FIRST; // UHCI descriptor chasing method - if (!maxsze) { - err("uhci_submit_control_urb: pipesize for pipe %x is zero", urb->pipe); - return -EINVAL; - } - dbg("uhci_submit_control start"); - alloc_qh (s, &qh); // alloc qh for this request - - if (!qh) + if (alloc_qh (s, &qh)) // alloc qh for this request return -ENOMEM; - alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first); // get td for setup stage - - if (!td) { + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) // get td for setup stage + { delete_qh (s, qh); return -ENOMEM; } @@ -749,8 +749,7 @@ while (len > 0) { int pktsze = len; - alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first); - if (!td) + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) goto fail_unmap_enomem; if (pktsze > maxsze) @@ -768,7 +767,7 @@ len -= pktsze; } - /* Build the final TD for control status */ + /* Build the final TD for control status */ /* It's only IN if the pipe is out AND we aren't expecting data */ destination &= ~UHCI_PID; @@ -780,9 +779,7 @@ destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ - alloc_td (s, &td, UHCI_PTR_DEPTH); - - if (!td) + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) goto fail_unmap_enomem; status &=~TD_CTRL_SPD; @@ -795,7 +792,6 @@ list_add (&qh->desc_list, &urb_priv->desc_list); - urb->status = -EINPROGRESS; queue_urb (s, urb); // queue before inserting in desc chain qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); @@ -821,7 +817,7 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb) { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; - urb_priv_t *urb_priv = urb->hcpriv; + urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL; uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL; unsigned long destination, status; char *data; @@ -829,33 +825,22 @@ int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); int info, len, last; int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method - urb_priv_t *upriv, *bpriv=NULL; if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; - if (urb->transfer_buffer_length < 0) { - err("Negative transfer length in submit_bulk"); - return -EINVAL; - } - - if (!maxsze) - return -EMSGSIZE; - queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i", urb,bulk_urb,urb->pipe,urb->transfer_buffer_length); upriv = (urb_priv_t*)urb->hcpriv; if (!bulk_urb) { - alloc_qh (s, &qh); // get qh for this request - - if (!qh) + if (alloc_qh (s, &qh)) // get qh for this request return -ENOMEM; if (urb->transfer_flags & USB_QUEUE_BULK) { - alloc_qh(s, &nqh); // placeholder for clean unlink - if (!nqh) { + if (alloc_qh(s, &nqh)) // placeholder for clean unlink + { delete_desc (s, qh); return -ENOMEM; } @@ -872,17 +857,16 @@ } if (urb->transfer_flags & USB_QUEUE_BULK) { - alloc_qh (s, &bqh); // "bottom" QH, - - if (!bqh) { + if (alloc_qh (s, &bqh)) // "bottom" QH + { if (!bulk_urb) { delete_desc(s, qh); delete_desc(s, nqh); } return -ENOMEM; } - bqh->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM); - bqh->hw.qh.head = cpu_to_le32(nqh->dma_addr | UHCI_PTR_QH); // element + set_qh_element(bqh, UHCI_PTR_TERM); + set_qh_head(bqh, nqh->dma_addr | UHCI_PTR_QH); // element upriv->bottom_qh = bqh; } queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh); @@ -901,9 +885,8 @@ do { // TBD: Really allow zero-length packets? int pktsze = len; - alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first); - - if (!td) { + if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first)) + { delete_qh (s, qh); return -ENOMEM; } @@ -924,7 +907,7 @@ last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET))); if (last) - td->hw.td.status |= cpu_to_le32(TD_CTRL_IOC); // last one generates INT + set_td_ioc(td); // last one generates INT insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); if (!first_td) @@ -941,11 +924,10 @@ if (urb->transfer_flags & USB_QUEUE_BULK) append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first); - urb->status = -EINPROGRESS; queue_urb_unlocked (s, urb); if (urb->transfer_flags & USB_QUEUE_BULK) - qh->hw.qh.element = cpu_to_le32(first_td->dma_addr); + set_qh_element(qh, first_td->dma_addr); else qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // arm QH @@ -988,10 +970,11 @@ } } /*-------------------------------------------------------------------*/ -// mode: 0: unlink but no deletion mark (step 1 of async_unlink) -// 1: regular (unlink/delete-mark) -// 2: deletion mark for QH (step 2 of async_unlink) -// looks a bit complicated because of all the bulk queueing goodies +/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink) + CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark) + CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink) + looks a bit complicated because of all the bulk queueing goodies +*/ _static void uhci_clean_transfer (uhci_t *s, urb_t *urb, uhci_desc_t *qh, int mode) { @@ -1005,18 +988,16 @@ if (!priv->next_queued_urb) { // no more appended bulk queues - queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p",urb, qh, bqh, priv->next_qh); + queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p", urb, qh, bqh, priv->next_qh); - if (priv->prev_queued_urb) { // qh not top of the queue - urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; + if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) { // qh not top of the queue + unsigned long flags; + urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; - if (mode != 2) { - unsigned long flags; - spin_lock_irqsave (&s->qh_lock, flags); prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical); - prevtd->hw.td.link = cpu_to_le32(priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh + set_td_link(prevtd, priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh mb(); queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd); spin_unlock_irqrestore (&s->qh_lock, flags); @@ -1024,19 +1005,18 @@ ppriv->bottom_qh = priv->bottom_qh; ppriv->next_queued_urb = NULL; } - } else { // queue is dead, qh is top of the queue - if (mode!=2) + if (mode != CLEAN_TRANSFER_DELETION_MARK) unlink_qh(s, qh); // remove qh from horizontal chain if (bqh) { // remove remainings of bulk queue nqh=priv->next_qh; - if (mode != 2) + if (mode != CLEAN_TRANSFER_DELETION_MARK) unlink_qh(s, nqh); // remove nqh from horizontal chain - if (mode) { + if (mode != CLEAN_TRANSFER_NO_DELETION) { // add helper QHs to free desc list nqh->last_used = bqh->last_used = now; list_add_tail (&nqh->horizontal, &s->free_desc); list_add_tail (&bqh->horizontal, &s->free_desc); @@ -1049,7 +1029,7 @@ queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p", urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh); - if (mode !=2) { // no work for cleanup at unlink-completion + if (mode != CLEAN_TRANSFER_DELETION_MARK) { // no work for cleanup at unlink-completion urb_t *nurb; unsigned long flags; @@ -1059,7 +1039,7 @@ if (!priv->prev_queued_urb) { // top QH prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal); - prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH); + set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); list_del (&qh->horizontal); // remove this qh form horizontal chain list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain } @@ -1072,18 +1052,18 @@ ppriv->bottom_qh = bnqh; ppriv->next_queued_urb = nurb; prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); - prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH); + set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH); } mb(); - spin_unlock_irqrestore (&s->qh_lock, flags); ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb; + spin_unlock_irqrestore (&s->qh_lock, flags); } } - if (mode) { + if (mode != CLEAN_TRANSFER_NO_DELETION) { qh->last_used = now; - list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion/kfree + list_add_tail (&qh->horizontal, &s->free_desc); // mark qh for later deletion/kfree } } /*-------------------------------------------------------------------*/ @@ -1134,9 +1114,56 @@ urb_priv->transfer_buffer_dma = 0; } } +/*-------------------------------------------------------------------*/ +/* needs urb_list_lock! + mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list + UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list +*/ +_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb, int mode) +{ + uhci_desc_t *qh; + urb_priv_t *urb_priv; + + async_dbg("unlink_urb_async called %p",urb); + + if ((urb->status == -EINPROGRESS) || + ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) + { + ((urb_priv_t*)urb->hcpriv)->started = ~0; // mark + dequeue_urb (s, urb); + + if (mode==UNLINK_ASYNC_STORE_URB) + list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb + + uhci_switch_timer_int(s); + s->unlink_urb_done = 1; + uhci_release_bandwidth(urb); + + urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" + urb_priv = (urb_priv_t*)urb->hcpriv; + + switch (usb_pipetype (urb->pipe)) { + case PIPE_INTERRUPT: + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + + case PIPE_ISOCHRONOUS: + uhci_clean_iso_step1 (s, urb_priv); + break; + case PIPE_BULK: + case PIPE_CONTROL: + qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION); + break; + } + ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); + return -EINPROGRESS; // completion will follow + } + + return 0; // URB already dead +} /*-------------------------------------------------------------------*/ -// unlinks an urb by dequeuing its qh, waits some frames and forgets it +// kills an urb by unlinking descriptors and waiting for at least one frame _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) { uhci_desc_t *qh; @@ -1150,43 +1177,36 @@ spin_lock(&urb->lock); if (urb->status == -EINPROGRESS) { - // URB probably still in work - dequeue_urb (s, urb); - uhci_switch_timer_int(s); - s->unlink_urb_done=1; - uhci_release_bandwidth(urb); - urb->status = -ENOENT; // mark urb as killed + // move descriptors out the the running chains, dequeue urb + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE); if (!in_interrupt()) spin_unlock(&urb->lock); - - spin_unlock_irqrestore (&s->urb_list_lock, flags); urb_priv = urb->hcpriv; + // cleanup the rest switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - case PIPE_ISOCHRONOUS: - uhci_clean_iso_step1(s, urb_priv); uhci_wait_ms(1); uhci_clean_iso_step2(s, urb_priv); break; case PIPE_BULK: case PIPE_CONTROL: - spin_lock_irqsave (&s->urb_list_lock, flags); qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_clean_transfer(s, urb, qh, 1); - spin_unlock_irqrestore (&s->urb_list_lock, flags); + uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); uhci_wait_ms(1); } - + + spin_unlock_irqrestore (&s->urb_list_lock, flags); + uhci_urb_dma_unmap(s, urb, urb->hcpriv); + urb->status = -ENOENT; // mark urb as killed + #ifdef DEBUG_SLAB kmem_cache_free (urb_priv_kmem, urb->hcpriv); #else @@ -1219,7 +1239,7 @@ struct list_head *q; urb_t *urb; struct usb_device *dev; - int pipe,now; + int now, type; urb_priv_t *urb_priv; q=s->urb_unlinked.next; @@ -1235,21 +1255,22 @@ if (!urb_priv) // avoid crash when URB is corrupted break; - if (force || - ((urb_priv->started != 0xffffffff) && (urb_priv->started != now))) { + if (force || ((urb_priv->started != ~0) && (urb_priv->started != now))) { async_dbg("async cleanup %p",urb); - switch (usb_pipetype (urb->pipe)) { // process descriptors + type=usb_pipetype (urb->pipe); + + switch (type) { // process descriptors case PIPE_CONTROL: - process_transfer (s, urb, 2); // 2: don't unlink (already done) + process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) break; case PIPE_BULK: if (!s->avoid_bulk.counter) - process_transfer (s, urb, 2); // don't unlink (already done) + process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done) else continue; break; case PIPE_ISOCHRONOUS: - process_iso (s, urb, 1); // force, don't unlink + process_iso (s, urb, PROCESS_ISO_FORCE); // force, don't unlink break; case PIPE_INTERRUPT: process_interrupt (s, urb); @@ -1259,8 +1280,7 @@ if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) urb->status = -ECONNRESET; // mark as asynchronously killed - pipe = urb->pipe; // completion may destroy all... - dev = urb->dev; + dev = urb->dev; // completion may destroy all... urb_priv = urb->hcpriv; list_del (&urb->urb_list); @@ -1274,7 +1294,8 @@ if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) urb->status = -ENOENT; // now the urb is really dead - switch (usb_pipetype (pipe)) { + + switch (type) { case PIPE_ISOCHRONOUS: case PIPE_INTERRUPT: uhci_clean_iso_step2(s, urb_priv); @@ -1293,50 +1314,7 @@ } } } - -/*-------------------------------------------------------------------*/ -// needs urb_list_lock! -_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb) -{ - uhci_desc_t *qh; - urb_priv_t *urb_priv; - - async_dbg("unlink_urb_async called %p",urb); - - if ((urb->status == -EINPROGRESS) || - ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) - { - ((urb_priv_t*)urb->hcpriv)->started = ~0; - - dequeue_urb (s, urb); - list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb - uhci_switch_timer_int(s); - - s->unlink_urb_done = 1; - - urb->status = -ECONNABORTED; // mark urb as "waiting to be killed" - urb_priv = (urb_priv_t*)urb->hcpriv; - - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - - case PIPE_ISOCHRONOUS: - uhci_clean_iso_step1 (s, urb_priv); - break; - - case PIPE_BULK: - case PIPE_CONTROL: - qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); - uhci_clean_transfer (s, urb, qh, 0); - break; - } - ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); - return -EINPROGRESS; // completion will follow - } - - return 0; // URB already dead -} + /*-------------------------------------------------------------------*/ _static int uhci_unlink_urb (urb_t *urb) { @@ -1365,7 +1343,7 @@ spin_lock(&urb->lock); uhci_release_bandwidth(urb); - ret = uhci_unlink_urb_async(s, urb); + ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); if (!in_interrupt()) spin_unlock(&urb->lock); @@ -1509,9 +1487,7 @@ if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe))) return -EINVAL; - ret = alloc_td (s, &td, UHCI_PTR_DEPTH); - - if (ret) + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) return -ENOMEM; status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | @@ -1526,7 +1502,6 @@ fill_td (td, status, info, urb_priv->transfer_buffer_dma); list_add_tail (&td->desc_list, &urb_priv->desc_list); - urb->status = -EINPROGRESS; queue_urb (s, urb); insert_td_horizontal (s, s->int_chain[nint], td); // store in INT-TDs @@ -1563,27 +1538,27 @@ goto err; } - // First try to get all TDs + memset(tdm, 0, urb->number_of_packets * sizeof (uhci_desc_t*)); + + // First try to get all TDs. Cause: Removing already inserted TDs can only be done + // racefree in three steps: unlink TDs, wait one frame, delete TDs. + // So, this solutions seems simpler... + for (n = 0; n < urb->number_of_packets; n++) { dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length); - if (!urb->iso_frame_desc[n].length) { - // allows ISO striping by setting length to zero in iso_descriptor - tdm[n] = 0; - continue; - } + if (!urb->iso_frame_desc[n].length) + continue; // allows ISO striping by setting length to zero in iso_descriptor + #ifdef ISO_SANITY_CHECK if(urb->iso_frame_desc[n].length > maxsze) { err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze); - tdm[n] = 0; ret=-EINVAL; } else #endif - ret = alloc_td (s, &td, UHCI_PTR_DEPTH); - - if (ret) { + if (alloc_td (s, &td, UHCI_PTR_DEPTH)) { int i; // Cleanup allocated TDs for (i = 0; i < n; n++) @@ -1596,31 +1571,26 @@ tdm[n] = td; } - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; //| (urb->transfer_flags&USB_DISABLE_SPD?0:TD_CTRL_SPD); + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe); - // Queue all allocated TDs for (n = 0; n < urb->number_of_packets; n++) { td = tdm[n]; if (!td) continue; - if (n == last) + if (n == last) { status |= TD_CTRL_IOC; + queue_urb (s, urb); + } fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21), urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset); list_add_tail (&td->desc_list, &urb_priv->desc_list); - if (n == last) { - urb->status = -EINPROGRESS; - queue_urb (s, urb); - } insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td); // store in iso-tds - //uhci_show_td(td); - } kfree (tdm); @@ -1630,7 +1600,6 @@ err: __restore_flags(flags); return ret; - } /*-------------------------------------------------------------------*/ // returns: 0 (no transfer queued), urb* (this urb already queued) @@ -1663,7 +1632,7 @@ { uhci_t *s; urb_priv_t *urb_priv; - int ret = 0; + int ret = 0, type; unsigned long flags; urb_t *queued_urb=NULL; int bustime; @@ -1676,10 +1645,23 @@ if (!s->running) return -ENODEV; - + + type = usb_pipetype (urb->pipe); + if (usb_pipedevice (urb->pipe) == s->rh.devnum) return rh_submit_urb (urb); /* virtual root hub */ + // Sanity checks + if (usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)) <= 0) { + err("uhci_submit_urb: pipesize for pipe %x is zero", urb->pipe); + return -EMSGSIZE; + } + + if (urb->transfer_buffer_length < 0 && type != PIPE_ISOCHRONOUS) { + err("uhci_submit_urb: Negative transfer length for urb %p", urb); + return -EINVAL; + } + usb_inc_dev_use (urb->dev); spin_lock_irqsave (&s->urb_list_lock, flags); @@ -1690,8 +1672,8 @@ queue_dbg("found bulk urb %p\n", queued_urb); - if ((usb_pipetype (urb->pipe) != PIPE_BULK) || - ((usb_pipetype (urb->pipe) == PIPE_BULK) && + if (( type != PIPE_BULK) || + ((type == PIPE_BULK) && (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) { spin_unlock_irqrestore (&s->urb_list_lock, flags); usb_dec_dev_use (urb->dev); @@ -1711,20 +1693,15 @@ return -ENOMEM; } + memset(urb_priv, 0, sizeof(urb_priv_t)); urb->hcpriv = urb_priv; INIT_LIST_HEAD (&urb_priv->desc_list); - urb_priv->flags = 0; + dbg("submit_urb: scheduling %p", urb); - urb_priv->next_queued_urb = NULL; - urb_priv->prev_queued_urb = NULL; - urb_priv->bottom_qh = NULL; - urb_priv->next_qh = NULL; - if (usb_pipetype (urb->pipe) == PIPE_CONTROL) + if (type == PIPE_CONTROL) urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet, sizeof(devrequest), PCI_DMA_TODEVICE); - else - urb_priv->setup_packet_dma = 0; if (urb->transfer_buffer_length) urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci, @@ -1733,10 +1710,8 @@ usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - else - urb_priv->transfer_buffer_dma = 0; - if (usb_pipetype (urb->pipe) == PIPE_BULK) { + if (type == PIPE_BULK) { if (queued_urb) { while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb) // find last queued bulk @@ -1751,7 +1726,7 @@ } else { spin_unlock_irqrestore (&s->urb_list_lock, flags); - switch (usb_pipetype (urb->pipe)) { + switch (type) { case PIPE_ISOCHRONOUS: if (urb->bandwidth == 0) { /* not yet checked/allocated */ if (urb->number_of_packets <= 0) { @@ -1760,14 +1735,13 @@ } bustime = usb_check_bandwidth (urb->dev, urb); - if (bustime < 0) { + if (bustime < 0) ret = bustime; - break; + else { + ret = uhci_submit_iso_urb(urb); + if (ret == 0) + usb_claim_bandwidth (urb->dev, urb, bustime, 1); } - - ret = uhci_submit_iso_urb(urb); - if (ret == 0) - usb_claim_bandwidth (urb->dev, urb, bustime, 1); } else { /* bandwidth is already set */ ret = uhci_submit_iso_urb(urb); } @@ -1810,8 +1784,7 @@ return 0; } -// Checks for URB timeout and removes bandwidth reclamation -// if URB idles too long +// Checks for URB timeout and removes bandwidth reclamation if URB idles too long _static void uhci_check_timeouts(uhci_t *s) { struct list_head *p,*p2; @@ -1834,7 +1807,7 @@ ((hcpriv->started + urb->timeout) < jiffies)) { urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK; async_dbg("uhci_check_timeout: timeout for %p",urb); - uhci_unlink_urb_async(s, urb); + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); } #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) && @@ -1973,7 +1946,6 @@ /*-------------------------------------------------------------------------*/ /* Root Hub INTs are polled by this timer, polling interval 20ms */ -/* This time is also used for URB-timeout checking */ _static int rh_init_int_timer (urb_t *urb) { @@ -2284,7 +2256,7 @@ spin_unlock_irqrestore (&s->urb_list_lock, flags); warn("forced removing of queued URB %p due to disconnect",urb); uhci_unlink_urb(urb); - urb->dev = NULL; // avoid further processing of this UR + urb->dev = NULL; // avoid further processing of this URB spin_lock_irqsave (&s->urb_list_lock, flags); p = s->urb_list.prev; } @@ -2325,13 +2297,34 @@ uhci_unlink_urb }; +_static void correct_data_toggles(urb_t *urb) +{ + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), + !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe))); + + while(urb) { + urb_priv_t *priv=urb->hcpriv; + uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list); + struct list_head *p = qh->vertical.next; + uhci_desc_t *td; + dbg("URB to correct %p\n", urb); + + for (; p != &qh->vertical; p = p->next) { + td = list_entry (p, uhci_desc_t, vertical); + td->hw.td.info^=cpu_to_le32(1<next_queued_urb; + } +} + /* * For IN-control transfers, process_transfer gets a bit more complicated, * since there are devices that return less data (eg. strings) than they * have announced. This leads to a queue abort due to the short packet, * the status stage is not executed. If this happens, the status stage * is manually re-executed. - * mode: 1: regular (unlink QH), 2: QHs already unlinked (for async unlink_urb) + * mode: PROCESS_TRANSFER_REGULAR: regular (unlink QH) + * PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb) */ _static int process_transfer (uhci_t *s, urb_t *urb, int mode) @@ -2356,7 +2349,7 @@ */ if (urb_priv->flags && - ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) ||(!(last_desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE))))) + ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) || !is_td_active(desc))) goto transfer_finished; urb->actual_length=0; @@ -2364,13 +2357,13 @@ for (; p != &qh->vertical; p = p->next) { desc = list_entry (p, uhci_desc_t, vertical); - if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) { // do not process active TDs - if (mode==2) // if called from async_unlink - uhci_clean_transfer(s, urb, qh, mode); + if (is_td_active(desc)) { // do not process active TDs + if (mode == CLEAN_TRANSFER_DELETION_MARK) // if called from async_unlink + uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK); return ret; } - actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff; // extract transfer parameters from TD + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); // extract transfer parameters from TD maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff; status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); @@ -2401,10 +2394,8 @@ if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) { if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) { - qh->hw.qh.element = cpu_to_le32(last_desc->dma_addr); // re-trigger status stage + set_qh_element(qh, last_desc->dma_addr); // re-trigger status stage dbg("short packet during control transfer, retrigger status stage @ %p",last_desc); - //uhci_show_td (desc); - //uhci_show_td (last_desc); urb_priv->flags = 1; // mark as short control packet return 0; } @@ -2421,7 +2412,24 @@ } - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle); + if (usb_pipetype (urb->pipe) == PIPE_BULK ) { /* toggle correction for short bulk transfers (nonqueued/queued) */ + + urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; + urb_t *next_queued_urb=priv->next_queued_urb; + + if (next_queued_urb) { + urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv; + uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list); + uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical); + + if (data_toggle == uhci_toggle (le32_to_cpu(first_td->hw.td.info))) { + err("process_transfer: fixed toggle"); + correct_data_toggles(next_queued_urb); + } + } + else + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle); + } transfer_finished: @@ -2454,7 +2462,7 @@ { desc = list_entry (p, uhci_desc_t, desc_list); - if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) { + if (is_td_active(desc)) { // do not process active TDs //dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status)); break; @@ -2466,7 +2474,7 @@ } // extract transfer parameters from TD - actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff; + actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); // see if EP is stalled @@ -2523,8 +2531,8 @@ mb(); } else { - uhci_unlink_urb_async(s, urb); - desc->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); // inactivate TD + uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB); + clr_td_ioc(desc); // inactivate TD } } } @@ -2532,7 +2540,9 @@ return ret; } -// mode: 1: force processing, don't unlink tds (already unlinked) +// mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs +// mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked) + _static int process_iso (uhci_t *s, urb_t *urb, int mode) { int i; @@ -2542,7 +2552,7 @@ uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list); dbg("urb contains iso request"); - if ((desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) && !mode) + if (is_td_active(desc) && mode==PROCESS_ISO_REGULAR) return -EXDEV; // last TD not finished urb->error_count = 0; @@ -2555,7 +2565,7 @@ desc = list_entry (p, uhci_desc_t, desc_list); //uhci_show_td(desc); - if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) { + if (is_td_active(desc)) { // means we have completed the last TD, but not the TDs before desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE); dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status)); @@ -2566,7 +2576,7 @@ goto err; } - if (!mode) + if (mode == PROCESS_ISO_REGULAR) unlink_td (s, desc, 1); if (urb->number_of_packets <= i) { @@ -2575,7 +2585,7 @@ goto err; } - urb->iso_frame_desc[i].actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff; + urb->iso_frame_desc[i].actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status)); urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe)); urb->actual_length += urb->iso_frame_desc[i].actual_length; @@ -2608,16 +2618,16 @@ switch (usb_pipetype (urb->pipe)) { case PIPE_CONTROL: - ret = process_transfer (s, urb, 1); + ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); break; case PIPE_BULK: if (!s->avoid_bulk.counter) - ret = process_transfer (s, urb, 1); + ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR); else return 0; break; case PIPE_ISOCHRONOUS: - ret = process_iso (s, urb, 0); + ret = process_iso (s, urb, PROCESS_ISO_REGULAR); break; case PIPE_INTERRUPT: ret = process_interrupt (s, urb); @@ -2712,19 +2722,20 @@ int was_unlinked = (urb->status == -ENOENT); urb->dev = NULL; spin_unlock(&s->urb_list_lock); + urb->complete ((struct urb *) urb); + // Re-submit the URB if ring-linked if (is_ring && !was_unlinked && !contains_killed) { urb->dev=usb_dev; uhci_submit_urb (urb); - } else - urb = 0; + + } + spin_unlock(&urb->lock); spin_lock(&s->urb_list_lock); } usb_dec_dev_use (usb_dev); - if (urb) - spin_unlock(&urb->lock); } } @@ -2752,11 +2763,16 @@ dbg("interrupt"); if (status != 1) { - warn("interrupt, status %x, frame# %i", status, - UHCI_GET_CURRENT_FRAME(s)); - + // Avoid too much error messages at a time + if ((jiffies - s->last_error_time > ERROR_SUPPRESSION_TIME)) { + warn("interrupt, status %x, frame# %i", status, + UHCI_GET_CURRENT_FRAME(s)); + s->last_error_time = jiffies; + } + // remove host controller halted state if ((status&0x20) && (s->running)) { + err("Host controller halted, trying to restart."); outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD); } //uhci_show_status (s); @@ -2799,8 +2815,8 @@ if ((jiffies - s->timeout_check) > (HZ/30)) uhci_check_timeouts(s); - clean_descs(s,0); - uhci_cleanup_unlink(s, 0); + clean_descs(s, CLEAN_NOT_FORCED); + uhci_cleanup_unlink(s, CLEAN_NOT_FORCED); uhci_switch_timer_int(s); spin_unlock (&s->urb_list_lock); @@ -2869,8 +2885,8 @@ reset_hc (s); wait_ms (1); - uhci_unlink_urbs (s, 0, 1); // Forced unlink of remaining URBs - uhci_cleanup_unlink (s, 1); // force cleanup of async killed URBs + uhci_unlink_urbs (s, 0, CLEAN_FORCED); // Forced unlink of remaining URBs + uhci_cleanup_unlink (s, CLEAN_FORCED); // force cleanup of async killed URBs usb_deregister_bus (s->bus); @@ -2943,11 +2959,9 @@ spin_lock_init (&s->qh_lock); spin_lock_init (&s->td_lock); atomic_set(&s->avoid_bulk, 0); - s->timeout_urbs = 0; s->irq = -1; s->io_addr = io_addr; s->io_size = io_size; - s->timeout_check = 0; s->uhci_pci=dev; bus = usb_alloc_bus (&uhci_device_operations); diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h --- v2.4.9/linux/drivers/usb/usb-uhci.h Mon Aug 27 12:41:45 2001 +++ linux/drivers/usb/usb-uhci.h Tue Aug 28 11:21:02 2001 @@ -2,7 +2,7 @@ #define __LINUX_UHCI_H /* - $Id: usb-uhci.h,v 1.55 2000/05/13 12:50:30 acher Exp $ + $Id: usb-uhci.h,v 1.58 2001/08/28 16:45:00 acher Exp $ */ #define MODNAME "usb-uhci" #define UHCI_LATENCY_TIMER 0 @@ -218,12 +218,35 @@ int timeout_urbs; struct pci_dev *uhci_pci; struct pci_pool *desc_pool; + long last_error_time; // last error output in uhci_interrupt() } uhci_t, *puhci_t; #define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH) #define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH) #define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM)) + +#define CLEAN_TRANSFER_NO_DELETION 0 +#define CLEAN_TRANSFER_REGULAR 1 +#define CLEAN_TRANSFER_DELETION_MARK 2 + +#define CLEAN_NOT_FORCED 0 +#define CLEAN_FORCED 1 + +#define PROCESS_ISO_REGULAR 0 +#define PROCESS_ISO_FORCE 1 + +#define UNLINK_ASYNC_STORE_URB 0 +#define UNLINK_ASYNC_DONT_STORE 1 + +#define is_td_active(desc) (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) + +#define set_qh_head(desc,val) (desc)->hw.qh.head=cpu_to_le32(val) +#define set_qh_element(desc,val) (desc)->hw.qh.element=cpu_to_le32(val) +#define set_td_link(desc,val) (desc)->hw.td.link=cpu_to_le32(val) +#define set_td_ioc(desc) (desc)->hw.td.status |= cpu_to_le32(TD_CTRL_IOC) +#define clr_td_ioc(desc) (desc)->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC) + /* ------------------------------------------------------------------------------------ Virtual Root HUB diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.9/linux/drivers/usb/usb.c Sun Aug 12 13:28:00 2001 +++ linux/drivers/usb/usb.c Tue Aug 28 11:22:21 2001 @@ -459,7 +459,7 @@ list_del(&bus->bus_list); write_unlock_irq (&usb_bus_list_lock); - usbdevfs_remove_bus(bus); + usbdevfs_remove_bus(bus); clear_bit(bus->busnum, busmap.busmap); @@ -707,7 +707,6 @@ private = NULL; for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) { - driver = list_entry(tmp, struct usb_driver, driver_list); tmp = tmp->next; @@ -725,17 +724,19 @@ break; } } + /* if driver not bound, leave defaults unchanged */ if (private == NULL) interface->act_altsetting = 0; - } - else /* "old style" driver */ - { + } else { /* "old style" driver */ down(&driver->serialize); private = driver->probe(dev, ifnum, NULL); up(&driver->serialize); } + /* probe() may have changed the config on us */ + interface = dev->actconfig->interface + ifnum; + if (private) { usb_driver_claim_interface(driver, interface, private); up(&dev->serialize); @@ -1178,7 +1179,7 @@ * @pipe: endpoint "pipe" to send the message to * @data: pointer to the data to send * @len: length in bytes of the data to send - * @actual_length: pointer to a location to put the actual length transfered in bytes + * @actual_length: pointer to a location to put the actual length transferred in bytes * @timeout: time to wait for the message to complete before timing out (if 0 the wait is forever) * * This function sends a simple bulk message to a specified endpoint @@ -1222,7 +1223,7 @@ } /*-------------------------------------------------------------------*/ -static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) +static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size) { struct usb_descriptor_header *header; unsigned char *begin; @@ -1266,8 +1267,7 @@ return -1; } - /* If we find another descriptor which is at or below us */ - /* in the descriptor heirarchy then we're done */ + /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || @@ -1308,7 +1308,7 @@ return parsed; } -static int usb_parse_interface(struct usb_device *dev, struct usb_interface *interface, unsigned char *buffer, int size) +static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) { int i, len, numskipped, retval, parsed = 0; struct usb_descriptor_header *header; @@ -1373,8 +1373,7 @@ return -1; } - /* If we find another descriptor which is at or below */ - /* us in the descriptor heirarchy then return */ + /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_CONFIG) || @@ -1440,7 +1439,7 @@ return -1; } - retval = usb_parse_endpoint(dev, ifp->endpoint + i, buffer, size); + retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); if (retval < 0) return retval; @@ -1460,7 +1459,7 @@ return parsed; } -int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor *config, char *buffer) +int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer) { int i, retval, size; struct usb_descriptor_header *header; @@ -1489,6 +1488,9 @@ buffer += config->bLength; size -= config->bLength; + config->extra = NULL; + config->extralen = 0; + for (i = 0; i < config->bNumInterfaces; i++) { int numskipped, len; char *begin; @@ -1505,8 +1507,7 @@ return -1; } - /* If we find another descriptor which is at or below */ - /* us in the descriptor heirarchy then we're done */ + /* If we find another "proper" descriptor then we're done */ if ((header->bDescriptorType == USB_DT_ENDPOINT) || (header->bDescriptorType == USB_DT_INTERFACE) || (header->bDescriptorType == USB_DT_CONFIG) || @@ -1525,22 +1526,23 @@ /* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ len = (int)(buffer - begin); - if (!len) { - config->extra = NULL; - config->extralen = 0; - } else { - config->extra = kmalloc(len, GFP_KERNEL); - if (!config->extra) { - err("couldn't allocate memory for config extra descriptors"); - config->extralen = 0; - return -1; - } + if (len) { + if (config->extralen) { + warn("extra config descriptor"); + } else { + config->extra = kmalloc(len, GFP_KERNEL); + if (!config->extra) { + err("couldn't allocate memory for config extra descriptors"); + config->extralen = 0; + return -1; + } - memcpy(config->extra, begin, len); - config->extralen = len; + memcpy(config->extra, begin, len); + config->extralen = len; + } } - retval = usb_parse_interface(dev, config->interface + i, buffer, size); + retval = usb_parse_interface(config->interface + i, buffer, size); if (retval < 0) return retval; @@ -2081,7 +2083,7 @@ dev->rawdescriptors[cfgno] = bigbuffer; - result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); + result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); if (result > 0) dbg("descriptor data left"); else if (result < 0) { diff -u --recursive --new-file v2.4.9/linux/drivers/usb/usbnet.c linux/drivers/usb/usbnet.c --- v2.4.9/linux/drivers/usb/usbnet.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usbnet.c Tue Aug 28 11:21:02 2001 @@ -0,0 +1,1567 @@ +/* + * USB Host-to-Host Links + * Copyright (C) 2000-2001 by David Brownell + */ + +/* + * This is used for "USB networking", connecting USB hosts as peers. + * + * It can be used with USB "network cables", for IP-over-USB communications; + * Ethernet speeds without the Ethernet. USB devices (including some PDAs) + * can support such links directly, replacing device-specific protocols + * with Internet standard ones. + * + * The links can be bridged using the Ethernet bridging (net/bridge) + * support as appropriate. Devices currently supported include: + * + * - AnchorChip 2720 + * - Belkin F5U104 (custom) + * - "Linux Devices" (like iPaq and similar SA-1100 based PDAs) + * - NetChip 1080 (interoperates with NetChip Win32 drivers) + * - Prolific PL-2301/2302 (replaces "plusb" driver) + * + * USB devices can implement their side of this protocol at the cost + * of two bulk endpoints; it's not restricted to "cable" applications. + * See the LINUXDEV support. + * + * + * TODO: + * + * This needs to be retested for bulk queuing problems ... earlier versions + * seemed to find different types of problems in each HCD. Once they're fixed, + * re-enable queues to get higher bandwidth utilization (without needing + * to tweak MTU for larger packets). + * + * Add support for more "network cable" chips; interop with their Win32 + * drivers may be a good thing. Test the AnchorChip 2720 support.. + * Figure out the initialization protocol used by the Prolific chips, + * for better robustness ... there's some powerup/reset handshake that's + * needed when only one end reboots. + * + * Use interrupt on PL230x to detect peer connect/disconnect, and call + * netif_carrier_{on,off} (?) appropriately. For Net1080, detect peer + * connect/disconnect with async control messages. + * + * Find some way to report "peer connected" network hotplug events; it'll + * likely mean updating the networking layer. (This has been discussed + * on the netdev list...) + * + * Craft smarter hotplug policy scripts ... ones that know how to arrange + * bridging with "brctl", and can handle static and dynamic ("pump") setups. + * Use those "peer connected" events. + * + * + * CHANGELOG: + * + * 13-sep-2000 experimental, new + * 10-oct-2000 usb_device_id table created. + * 28-oct-2000 misc fixes; mostly, discard more TTL-mangled rx packets. + * 01-nov-2000 usb_device_id table and probing api update by + * Adam J. Richter . + * 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info + * and prolific support, isolate net1080-specific bits, cleanup. + * fix unlink_urbs oops in D3 PM resume code path. + * 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ... + * 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it; + * AnchorChips 2720 support (from spec) for testing; + * fix bit-ordering problem with ethernet multicast addr + * 19-feb-2001 Support for clearing halt conditions. SA1100 UDC support + * updates. Oleg Drokin (green@iXcelerator.com) + * 25-mar-2001 More SA-1100 updates, including workaround for ip problem + * expecting cleared skb->cb and framing change to match latest + * handhelds.org version (Oleg). Enable device IDs from the + * Win32 Belkin driver; other cleanups (db). + * 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various + * cleanups for problems not yet seen in the field. (db) + * + *-------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #define DEBUG // error path messages, extra info +// #define VERBOSE // more; success messages +// #define REALLY_QUEUE + +#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) +# define DEBUG +#endif +#include + + +#define CONFIG_USB_AN2720 +#define CONFIG_USB_BELKIN_F5U104 +#define CONFIG_USB_LINUXDEV +#define CONFIG_USB_NET1080 +#define CONFIG_USB_PL2301 + + +/*-------------------------------------------------------------------------*/ + +/* + * Nineteen USB 1.1 max size bulk transactions per frame (ms), max. + * Several dozen bytes of IPv4 data can fit in two such transactions. + * One maximum size Ethernet packet takes twenty four of them. + */ +#ifdef REALLY_QUEUE +#define RX_QLEN 4 +#define TX_QLEN 4 +#else +#define RX_QLEN 1 +#define TX_QLEN 1 +#endif + +// packets are always ethernet inside +// ... except they can be bigger (up to 64K with this framing) +#define MIN_PACKET sizeof(struct ethhdr) +#define MAX_PACKET 32768 + +// reawaken network queue this soon after stopping; else watchdog barks +#define TX_TIMEOUT_JIFFIES (5*HZ) + +// for vendor-specific control operations +#define CONTROL_TIMEOUT_MS (500) /* msec */ +#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000) + +// between wakeups +#define UNLINK_TIMEOUT_JIFFIES ((3 /*ms*/ * HZ)/1000) + +/*-------------------------------------------------------------------------*/ + +// list of all devices we manage +static DECLARE_MUTEX (usbnet_mutex); +static LIST_HEAD (usbnet_list); + +// randomly generated ethernet address +static u8 node_id [ETH_ALEN]; + +// state we keep for each device we handle +struct usbnet { + // housekeeping + struct usb_device *udev; + struct driver_info *driver_info; + struct semaphore mutex; + struct list_head dev_list; + wait_queue_head_t *wait; + + // protocol/interface state + struct net_device net; + struct net_device_stats stats; + u16 packet_id; + + // various kinds of pending driver work + struct sk_buff_head rxq; + struct sk_buff_head txq; + struct sk_buff_head done; + struct tasklet_struct bh; + struct tq_struct ctrl_task; +}; + +// device-specific info used by the driver +struct driver_info { + char *description; + + int flags; +#define FLAG_FRAMING 0x0001 /* guard against device dropouts */ + + /* reset device ... can sleep */ + int (*reset)(struct usbnet *); + + /* see if peer is connected ... can sleep */ + int (*check_connect)(struct usbnet *); + + // FIXME -- also an interrupt mechanism + + /* framework currently "knows" bulk EPs talk packets */ + int in; /* rx endpoint */ + int out; /* tx endpoint */ + int epsize; +}; + +#define EP_SIZE(usbnet) ((usbnet)->driver_info->epsize) + +// we record the state for each of our queued skbs +enum skb_state { + illegal = 0, + tx_start, tx_done, + rx_start, rx_done, rx_cleanup +}; + +struct skb_data { // skb->cb is one of these + struct urb *urb; + struct usbnet *dev; + enum skb_state state; + size_t length; +}; + + +#define mutex_lock(x) down(x) +#define mutex_unlock(x) up(x) + +#define RUN_CONTEXT (in_irq () ? "in_irq" \ + : (in_interrupt () ? "in_interrupt" : "can sleep")) + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +#define devdbg(usbnet, fmt, arg...) \ + printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net.name, ## arg) +#else +#define devdbg(usbnet, fmt, arg...) do {} while(0) +#endif + +#define devinfo(usbnet, fmt, arg...) \ + printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg) + +/*------------------------------------------------------------------------- + * + * NetChip framing of ethernet packets, supporting additional error + * checks for links that may drop bulk packets from inside messages. + * Odd USB length == always short read for last usb packet. + * - nc_header + * - Ethernet header (14 bytes) + * - payload + * - (optional padding byte, if needed so length becomes odd) + * - nc_trailer + * + * This framing is to be avoided for non-NetChip devices. + */ + +struct nc_header { // packed: + u16 hdr_len; // sizeof nc_header (LE, all) + u16 packet_len; // payload size (including ethhdr) + u16 packet_id; // detects dropped packets +#define MIN_HEADER 6 + + // all else is optional, and must start with: + // u16 vendorId; // from usb-if + // u16 productId; +} __attribute__((__packed__)); + +#define PAD_BYTE ((unsigned char)0xAC) + +struct nc_trailer { + u16 packet_id; +} __attribute__((__packed__)); + +// packets may use FLAG_FRAMING and optional pad +#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \ + + sizeof (struct ethhdr) \ + + (mtu) \ + + 1 \ + + sizeof (struct nc_trailer)) + +#define MIN_FRAMED FRAMED_SIZE(0) + + + +#ifdef CONFIG_USB_AN2720 + +/*------------------------------------------------------------------------- + * + * AnchorChips 2720 driver ... http://www.cypress.com + * + * This doesn't seem to have a way to detect whether the peer is + * connected, or need any reset handshaking. It's got pretty big + * internal buffers (handles most of a frame's worth of data). + * Chip data sheets don't describe any vendor control messages. + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info an2720_info = { + description: "AnchorChips/Cypress 2720", + // no reset available! + // no check_connect available! + + in: 2, out: 2, // direction distinguishes these + epsize: 64, +}; + +#endif /* CONFIG_USB_AN2720 */ + + + +#ifdef CONFIG_USB_BELKIN_F5U104 + +/*------------------------------------------------------------------------- + * + * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info belkin_info = { + description: "Belkin USB Direct Connect (F5U104)", + + in: 1, out: 1, // direction distinguishes these + epsize: 64, +}; + +#endif /* CONFIG_USB_BELKIN_F5U104 */ + + + +#ifdef CONFIG_USB_LINUXDEV + +/*------------------------------------------------------------------------- + * + * This could talk to a device that uses Linux, such as a PDA or + * an embedded system, or in fact to any "smart" device using this + * particular mapping of USB and Ethernet. + * + * Such a Linux host would need a "USB Device Controller" hardware + * (not "USB Host Controller"), and a network driver talking to that + * hardware. + * + * One example is Intel's SA-1100 chip, which integrates basic USB + * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA. + * + *-------------------------------------------------------------------------*/ + + +static const struct driver_info linuxdev_info = { + description: "Linux Device", + // no reset defined (yet?) + // no check_connect needed! + in: 2, out: 1, + epsize: 64, +}; + +#endif /* CONFIG_USB_LINUXDEV */ + + + +#ifdef CONFIG_USB_NET1080 + +/*------------------------------------------------------------------------- + * + * Netchip 1080 driver ... http://www.netchip.com + * + *-------------------------------------------------------------------------*/ + +/* + * Zero means no timeout; else, how long a 64 byte bulk packet may be queued + * before the hardware drops it. If that's done, the driver will need to + * frame network packets to guard against the dropped USB packets. The win32 + * driver sets this for both sides of the link. + */ +#define NC_READ_TTL_MS ((u8)255) // ms + +/* + * We ignore most registers and EEPROM contents. + */ +#define REG_USBCTL ((u8)0x04) +#define REG_TTL ((u8)0x10) +#define REG_STATUS ((u8)0x11) + +/* + * Vendor specific requests to read/write data + */ +#define REQUEST_REGISTER ((u8)0x10) +#define REQUEST_EEPROM ((u8)0x11) + +static int +nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr) +{ + int status = usb_control_msg (dev->udev, + usb_rcvctrlpipe (dev->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, regnum, + retval_ptr, sizeof *retval_ptr, + CONTROL_TIMEOUT_JIFFIES); + if (status > 0) + status = 0; + if (!status) + le16_to_cpus (retval_ptr); + return status; +} + +static inline int +nc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr) +{ + return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr); +} + +// no retval ... can become async, usable in_interrupt() +static void +nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value) +{ + usb_control_msg (dev->udev, + usb_sndctrlpipe (dev->udev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, regnum, + 0, 0, // data is in setup packet + CONTROL_TIMEOUT_JIFFIES); +} + +static inline void +nc_register_write (struct usbnet *dev, u8 regnum, u16 value) +{ + nc_vendor_write (dev, REQUEST_REGISTER, regnum, value); +} + + +#if 0 +static void nc_dump_registers (struct usbnet *dev) +{ + u8 reg; + u16 *vp = kmalloc (sizeof (u16)); + + if (!vp) { + dbg ("no memory?"); + return; + } + + dbg ("%s registers:", dev->net.name); + for (reg = 0; reg < 0x20; reg++) { + int retval; + + // reading some registers is trouble + if (reg >= 0x08 && reg <= 0xf) + continue; + if (reg >= 0x12 && reg <= 0x1e) + continue; + + retval = nc_register_read (dev, reg, vp); + if (retval < 0) + dbg ("%s reg [0x%x] ==> error %d", + dev->net.name, reg, retval); + else + dbg ("%s reg [0x%x] = 0x%x", + dev->net.name, reg, *vp); + } + kfree (vp); +} +#endif + + +/*-------------------------------------------------------------------------*/ + +/* + * Control register + */ + +#define USBCTL_WRITABLE_MASK 0x1f0f +// bits 15-13 reserved, r/o +#define USBCTL_ENABLE_LANG (1 << 12) +#define USBCTL_ENABLE_MFGR (1 << 11) +#define USBCTL_ENABLE_PROD (1 << 10) +#define USBCTL_ENABLE_SERIAL (1 << 9) +#define USBCTL_ENABLE_DEFAULTS (1 << 8) +// bits 7-4 reserved, r/o +#define USBCTL_FLUSH_OTHER (1 << 3) +#define USBCTL_FLUSH_THIS (1 << 2) +#define USBCTL_DISCONN_OTHER (1 << 1) +#define USBCTL_DISCONN_THIS (1 << 0) + +static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl) +{ +#ifdef DEBUG + devdbg (dev, "net1080 %03d/%03d usbctl 0x%x:%s%s%s%s%s;" + " this%s%s;" + " other%s%s; r/o 0x%x", + dev->udev->bus->busnum, dev->udev->devnum, + usbctl, + (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", + (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", + (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", + (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", + (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", + + (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", + (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", + usbctl & ~USBCTL_WRITABLE_MASK + ); +#endif +} + +/*-------------------------------------------------------------------------*/ + +/* + * Status register + */ + +#define STATUS_PORT_A (1 << 15) + +#define STATUS_CONN_OTHER (1 << 14) +#define STATUS_SUSPEND_OTHER (1 << 13) +#define STATUS_MAILBOX_OTHER (1 << 12) +#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) + +#define STATUS_CONN_THIS (1 << 6) +#define STATUS_SUSPEND_THIS (1 << 5) +#define STATUS_MAILBOX_THIS (1 << 4) +#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) + +#define STATUS_UNSPEC_MASK 0x0c8c +#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) + + +static inline void nc_dump_status (struct usbnet *dev, u16 status) +{ +#ifdef DEBUG + devdbg (dev, "net1080 %03d/%03d status 0x%x:" + " this (%c) PKT=%d%s%s%s;" + " other PKT=%d%s%s%s; unspec 0x%x", + dev->udev->bus->busnum, dev->udev->devnum, + status, + + // XXX the packet counts don't seem right + // (1 at reset, not 0); maybe UNSPEC too + + (status & STATUS_PORT_A) ? 'A' : 'B', + STATUS_PACKETS_THIS (status), + (status & STATUS_CONN_THIS) ? " CON" : "", + (status & STATUS_SUSPEND_THIS) ? " SUS" : "", + (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", + + STATUS_PACKETS_OTHER (status), + (status & STATUS_CONN_OTHER) ? " CON" : "", + (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", + (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", + + status & STATUS_UNSPEC_MASK + ); +#endif +} + +/*-------------------------------------------------------------------------*/ + +/* + * TTL register + */ + +#define TTL_THIS(ttl) (0x00ff & ttl) +#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8)) +#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this)))) + +static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl) +{ +#ifdef DEBUG + devdbg (dev, "net1080 %03d/%03d ttl 0x%x this = %d, other = %d", + dev->udev->bus->busnum, dev->udev->devnum, + ttl, + + TTL_THIS (ttl), + TTL_OTHER (ttl) + ); +#endif +} + +/*-------------------------------------------------------------------------*/ + +static int net1080_reset (struct usbnet *dev) +{ + u16 usbctl, status, ttl; + u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL); + int retval; + + if (!vp) + return -ENOMEM; + + // nc_dump_registers (dev); + + if ((retval = nc_register_read (dev, REG_STATUS, vp)) < 0) { + dbg ("can't read dev %d status: %d", dev->udev->devnum, retval); + goto done; + } + status = *vp; + // nc_dump_status (dev, status); + + if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) { + dbg ("can't read USBCTL, %d", retval); + goto done; + } + usbctl = *vp; + // nc_dump_usbctl (dev, usbctl); + + nc_register_write (dev, REG_USBCTL, + USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER); + + if ((retval = nc_register_read (dev, REG_TTL, vp)) < 0) { + dbg ("can't read TTL, %d", retval); + goto done; + } + ttl = *vp; + // nc_dump_ttl (dev, ttl); + + nc_register_write (dev, REG_TTL, + MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) ); + dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS); + + devdbg (dev, "port %c, peer %sconnected", + (status & STATUS_PORT_A) ? 'A' : 'B', + (status & STATUS_CONN_OTHER) ? "" : "dis" + ); + retval = 0; + +done: + kfree (vp); + return retval; +} + +static int net1080_check_connect (struct usbnet *dev) +{ + int retval; + u16 status; + u16 *vp = kmalloc (sizeof (u16), GFP_KERNEL); + + if (!vp) + return -ENOMEM; + retval = nc_register_read (dev, REG_STATUS, vp); + status = *vp; + kfree (vp); + if (retval != 0) { + dbg ("%s net1080_check_conn read - %d", dev->net.name, retval); + return retval; + } + if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER) + return -ENOLINK; + return 0; +} + +static const struct driver_info net1080_info = { + description: "NetChip TurboCONNECT", + flags: FLAG_FRAMING, + reset: net1080_reset, + check_connect: net1080_check_connect, + + in: 1, out: 1, // direction distinguishes these + epsize: 64, +}; + +#endif /* CONFIG_USB_NET1080 */ + + + +#ifdef CONFIG_USB_PL2301 + +/*------------------------------------------------------------------------- + * + * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com + * + *-------------------------------------------------------------------------*/ + +/* + * Bits 0-4 can be used for software handshaking; they're set from + * one end, cleared from the other, "read" with the interrupt byte. + */ +#define PL_S_EN (1<<7) /* (feature only) suspend enable */ +/* reserved bit -- rx ready (6) ? */ +#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */ +#define PL_RESET_OUT (1<<4) /* reset output pipe */ +#define PL_RESET_IN (1<<3) /* reset input pipe */ +#define PL_TX_C (1<<2) /* transmission complete */ +#define PL_TX_REQ (1<<1) /* transmission received */ +#define PL_PEER_E (1<<0) /* peer exists */ + +static inline int +pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index) +{ + return usb_control_msg (dev->udev, + usb_rcvctrlpipe (dev->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + val, index, + 0, 0, + CONTROL_TIMEOUT_JIFFIES); +} + +static inline int +pl_clear_QuickLink_features (struct usbnet *dev, int val) +{ + return pl_vendor_req (dev, 1, (u8) val, 0); +} + +static inline int +pl_set_QuickLink_features (struct usbnet *dev, int val) +{ + return pl_vendor_req (dev, 3, (u8) val, 0); +} + +/*-------------------------------------------------------------------------*/ + +static int pl_reset (struct usbnet *dev) +{ + return pl_set_QuickLink_features (dev, + PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); +} + +static int pl_check_connect (struct usbnet *dev) +{ + // FIXME test interrupt data PL_PEER_E bit + // plus, there's some handshake done by + // the prolific win32 driver... + dbg ("%s: assuming peer is connected", dev->net.name); + return 0; +} + +static const struct driver_info prolific_info = { + description: "Prolific PL-2301/PL-2302", + reset: pl_reset, + check_connect: pl_check_connect, + + in: 3, out: 2, + epsize: 64, +}; + +#endif /* CONFIG_USB_PL2301 */ + + + +/*------------------------------------------------------------------------- + * + * Network Device Driver (peer link to "Host Device", from USB host) + * + *-------------------------------------------------------------------------*/ + +static int usbnet_change_mtu (struct net_device *net, int new_mtu) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + + if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET) + return -EINVAL; + if (((dev->driver_info->flags) & FLAG_FRAMING)) { + if (FRAMED_SIZE (new_mtu) > MAX_PACKET) + return -EINVAL; + // no second zero-length packet read wanted after mtu-sized packets + } else if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0) + return -EDOM; + net->mtu = new_mtu; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct net_device_stats *usbnet_get_stats (struct net_device *net) +{ + return &((struct usbnet *) net->priv)->stats; +} + +/*-------------------------------------------------------------------------*/ + +/* urb completions are currently in_irq; avoid doing real work then. */ + +static void defer_bh (struct usbnet *dev, struct sk_buff *skb) +{ + struct sk_buff_head *list = skb->list; + unsigned long flags; + + spin_lock_irqsave (&list->lock, flags); + __skb_unlink (skb, list); + spin_unlock (&list->lock); + spin_lock (&dev->done.lock); + __skb_queue_tail (&dev->done, skb); + if (dev->done.qlen == 1) + tasklet_schedule (&dev->bh); + spin_unlock_irqrestore (&dev->done.lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +static void rx_complete (struct urb *urb); + +static void rx_submit (struct usbnet *dev, struct urb *urb, int flags) +{ + struct sk_buff *skb; + struct skb_data *entry; + int retval = 0; + unsigned long lockflags; + size_t size; + + size = (dev->driver_info->flags & FLAG_FRAMING) + ? FRAMED_SIZE (dev->net.mtu) + : (sizeof (struct ethhdr) + dev->net.mtu); + if ((skb = alloc_skb (size, flags)) == 0) { + dbg ("no rx skb"); + tasklet_schedule (&dev->bh); + usb_free_urb (urb); + return; + } + + entry = (struct skb_data *) skb->cb; + entry->urb = urb; + entry->dev = dev; + entry->state = rx_start; + entry->length = 0; + + FILL_BULK_URB (urb, dev->udev, + usb_rcvbulkpipe (dev->udev, dev->driver_info->in), + skb->data, size, rx_complete, skb); +#ifdef REALLY_QUEUE + urb->transfer_flags |= USB_QUEUE_BULK; +#endif + + spin_lock_irqsave (&dev->rxq.lock, lockflags); + + if (netif_running (&dev->net)) { + if ((retval = usb_submit_urb (urb)) != 0) { + dbg ("%s rx submit, %d", dev->net.name, retval); + tasklet_schedule (&dev->bh); + } else { + __skb_queue_tail (&dev->rxq, skb); + } + } else { + dbg ("rx: stopped"); + retval = -ENOLINK; + } + spin_unlock_irqrestore (&dev->rxq.lock, lockflags); + if (retval) { + dev_kfree_skb_any (skb); + usb_free_urb (urb); + } +} + + +/*-------------------------------------------------------------------------*/ + +static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) +{ + if (dev->driver_info->flags & FLAG_FRAMING) { + struct nc_header *header; + struct nc_trailer *trailer; + + if (!(skb->len & 0x01) + || MIN_FRAMED > skb->len + || skb->len > FRAMED_SIZE (dev->net.mtu)) { + dev->stats.rx_frame_errors++; + dbg ("rx framesize %d range %d..%d mtu %d", skb->len, + MIN_FRAMED, FRAMED_SIZE (dev->net.mtu), + dev->net.mtu + ); + goto error; + } + + header = (struct nc_header *) skb->data; + le16_to_cpus (&header->hdr_len); + le16_to_cpus (&header->packet_len); + if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) { + dev->stats.rx_frame_errors++; + dbg ("packet too big, %d", header->packet_len); + goto error; + } else if (header->hdr_len < MIN_HEADER) { + dev->stats.rx_frame_errors++; + dbg ("header too short, %d", header->hdr_len); + goto error; + } else if (header->hdr_len > MIN_HEADER) { + // out of band data for us? + dbg ("header OOB, %d bytes", + header->hdr_len - MIN_HEADER); + // switch (vendor/product ids) { ... } + } + skb_pull (skb, header->hdr_len); + + trailer = (struct nc_trailer *) + (skb->data + skb->len - sizeof *trailer); + skb_trim (skb, skb->len - sizeof *trailer); + + if ((header->packet_len & 0x01) == 0) { + if (skb->data [header->packet_len] != PAD_BYTE) { + dev->stats.rx_frame_errors++; + dbg ("bad pad"); + goto error; + } + skb_trim (skb, skb->len - 1); + } + if (skb->len != header->packet_len) { + dev->stats.rx_frame_errors++; + dbg ("bad packet len %d (expected %d)", + skb->len, header->packet_len); + goto error; + } + if (header->packet_id != get_unaligned (&trailer->packet_id)) { + dev->stats.rx_fifo_errors++; + dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", + header->packet_id, trailer->packet_id); + goto error; + } +#if 0 + devdbg (dev, "frame hdr_len, + header->packet_len, header->packet_id); +#endif + } else { + // we trust the network stack to remove + // the extra byte we may have appended + } + + if (skb->len) { + int status; + +// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ? + + skb->dev = &dev->net; + skb->protocol = eth_type_trans (skb, &dev->net); + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + +#ifdef VERBOSE + devdbg (dev, "< rx, len %d, type 0x%x", + skb->len + sizeof (struct ethhdr), skb->protocol); +#endif + memset (skb->cb,0,sizeof(struct skb_data)); + status = netif_rx (skb); + if (status != NET_RX_SUCCESS) + devdbg (dev, "netif_rx status %d", status); + } else { + dbg ("drop"); +error: + dev->stats.rx_errors++; + skb_queue_tail (&dev->done, skb); + } +} + +/*-------------------------------------------------------------------------*/ + +static void rx_complete (struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct skb_data *entry = (struct skb_data *) skb->cb; + struct usbnet *dev = entry->dev; + int urb_status = urb->status; + + skb_put (skb, urb->actual_length); + entry->state = rx_done; + entry->urb = 0; + + switch (urb_status) { + // success + case 0: + if (MIN_PACKET > skb->len || skb->len > MAX_PACKET) { + entry->state = rx_cleanup; + dev->stats.rx_errors++; + dev->stats.rx_length_errors++; + dbg ("rx length %d", skb->len); + } + break; + + // software-driven interface shutdown + case -ECONNRESET: // usb-ohci, usb-uhci + case -ECONNABORTED: // uhci ... for usb-uhci, INTR + dbg ("%s shutdown, code %d", dev->net.name, urb_status); + entry->state = rx_cleanup; + // do urb frees only in the tasklet + entry->urb = urb; + urb = 0; + break; + + // data overrun ... flush fifo? + case -EOVERFLOW: + dev->stats.rx_over_errors++; + // FALLTHROUGH + + default: + // on unplug we'll get a burst of ETIMEDOUT/EILSEQ + // till the khubd gets and handles its interrupt. + entry->state = rx_cleanup; + dev->stats.rx_errors++; + dbg ("%s rx: status %d", dev->net.name, urb_status); + break; + } + + defer_bh (dev, skb); + + if (urb) { + if (netif_running (&dev->net)) { + rx_submit (dev, urb, GFP_ATOMIC); + return; + } + } +#ifdef VERBOSE + dbg ("no read resubmitted"); +#endif /* VERBOSE */ +} + +/*-------------------------------------------------------------------------*/ + +// unlink pending rx/tx; completion handlers do all other cleanup + +static int unlink_urbs (struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb, *skbnext; + int count = 0; + + spin_lock_irqsave (&q->lock, flags); + for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) { + struct skb_data *entry; + struct urb *urb; + int retval; + + entry = (struct skb_data *) skb->cb; + urb = entry->urb; + skbnext = skb->next; + + // during some PM-driven resume scenarios, + // these (async) unlinks complete immediately + retval = usb_unlink_urb (urb); + if (retval < 0) + dbg ("unlink urb err, %d", retval); + else + count++; + } + spin_unlock_irqrestore (&q->lock, flags); + return count; +} + + +/*-------------------------------------------------------------------------*/ + +// precondition: never called in_interrupt + +static int usbnet_stop (struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + int temp; + DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); + DECLARE_WAITQUEUE (wait, current); + + mutex_lock (&dev->mutex); + netif_stop_queue(net); + + devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", + dev->stats.rx_packets, dev->stats.tx_packets, + dev->stats.rx_errors, dev->stats.tx_errors + ); + + // ensure there are no more active urbs + add_wait_queue (&unlink_wakeup, &wait); + dev->wait = &unlink_wakeup; + temp = unlink_urbs (&dev->txq) + unlink_urbs (&dev->rxq); + + // maybe wait for deletions to finish. + while (skb_queue_len (&dev->rxq) + && skb_queue_len (&dev->txq) + && skb_queue_len (&dev->done)) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout (UNLINK_TIMEOUT_JIFFIES); + dbg ("waited for %d urb completions", temp); + } + dev->wait = 0; + remove_wait_queue (&unlink_wakeup, &wait); + + mutex_unlock (&dev->mutex); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +// posts reads, and enables write queing + +// precondition: never called in_interrupt + +static int usbnet_open (struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + int retval = 0; + struct driver_info *info = dev->driver_info; + + mutex_lock (&dev->mutex); + + // put into "known safe" state + if (info->reset && (retval = info->reset (dev)) < 0) { + devinfo (dev, "open reset fail (%d) usbnet %03d/%03d, %s", + retval, + dev->udev->bus->busnum, dev->udev->devnum, + info->description); + goto done; + } + + // insist peer be connected + if (info->check_connect && (retval = info->check_connect (dev)) < 0) { + devdbg (dev, "can't open; %d", retval); + goto done; + } + + netif_start_queue (net); + devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %sframed", + RX_QLEN, TX_QLEN, dev->net.mtu, + (info->flags & FLAG_FRAMING) ? "" : "un" + ); + + // delay posting reads until we're fully open + tasklet_schedule (&dev->bh); +done: + mutex_unlock (&dev->mutex); + return retval; +} + +/*-------------------------------------------------------------------------*/ + +/* usb_clear_halt cannot be called in interrupt context */ + +static void +tx_clear_halt(void *data) +{ + struct usbnet *dev = data; + + usb_clear_halt (dev->udev, + usb_sndbulkpipe (dev->udev, dev->driver_info->out)); + netif_wake_queue (&dev->net); +} + +/*-------------------------------------------------------------------------*/ + +static void tx_complete (struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct skb_data *entry = (struct skb_data *) skb->cb; + struct usbnet *dev = entry->dev; + + if (urb->status == USB_ST_STALL) { + if (dev->ctrl_task.sync == 0) { + dev->ctrl_task.routine = tx_clear_halt; + dev->ctrl_task.data = dev; + schedule_task(&dev->ctrl_task); + } else { + dbg ("Cannot clear TX stall"); + } + } + urb->dev = 0; + entry->state = tx_done; + defer_bh (dev, skb); +} + +/*-------------------------------------------------------------------------*/ + +static void usbnet_tx_timeout (struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + + unlink_urbs (&dev->txq); + tasklet_schedule (&dev->bh); + + // FIXME: device recovery -- reset? +} + +/*-------------------------------------------------------------------------*/ + +static inline struct sk_buff *fixup_skb (struct sk_buff *skb, int flags) +{ + int padlen; + struct sk_buff *skb2; + + padlen = ((skb->len + sizeof (struct nc_header) + + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1; + if (!skb_cloned (skb)) { + int headroom = skb_headroom (skb); + int tailroom = skb_tailroom (skb); + + if ((padlen + sizeof (struct nc_trailer)) <= tailroom + && sizeof (struct nc_header) <= headroom) + return skb; + + if ((sizeof (struct nc_header) + padlen + + sizeof (struct nc_trailer)) < + (headroom + tailroom)) { + skb->data = memmove (skb->head + + sizeof (struct nc_header), + skb->data, skb->len); + skb->tail = skb->data + skb->len; + return skb; + } + } + skb2 = skb_copy_expand (skb, + sizeof (struct nc_header), + sizeof (struct nc_trailer) + padlen, + flags); + dev_kfree_skb_any (skb); + return skb2; +} + +/*-------------------------------------------------------------------------*/ + +static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) +{ + struct usbnet *dev = (struct usbnet *) net->priv; + int length = skb->len; + int retval = NET_XMIT_SUCCESS; + struct urb *urb = 0; + struct skb_data *entry; + struct nc_header *header = 0; + struct nc_trailer *trailer = 0; + struct driver_info *info = dev->driver_info; + int flags; + + flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; + + if (info->flags & FLAG_FRAMING) { + struct sk_buff *skb2; + skb2 = fixup_skb (skb, flags); + if (!skb2) { + dbg ("can't fixup skb"); + goto drop; + } + skb = skb2; + } + + if (!(urb = usb_alloc_urb (0))) { + dbg ("no urb"); + goto drop; + } + + entry = (struct skb_data *) skb->cb; + entry->urb = urb; + entry->dev = dev; + entry->state = tx_start; + entry->length = length; + + if (info->flags & FLAG_FRAMING) { + header = (struct nc_header *) skb_push (skb, sizeof *header); + header->hdr_len = cpu_to_le16 (sizeof (*header)); + header->packet_len = cpu_to_le16 (length); + if (!((skb->len + sizeof *trailer) & 0x01)) + *skb_put (skb, 1) = PAD_BYTE; + trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer); + } else if ((length % EP_SIZE (dev)) == 0) { + if (skb_shared (skb)) { + struct sk_buff *skb2; + skb2 = skb_unshare (skb, flags); + if (!skb2) { + dbg ("can't unshare skb"); + goto drop; + } + skb = skb2; + } + skb->len++; + } + + FILL_BULK_URB (urb, dev->udev, + usb_sndbulkpipe (dev->udev, info->out), + skb->data, skb->len, tx_complete, skb); + // Idle-but-posted reads with UHCI really chew up + // PCI bandwidth unless FSBR is disabled + urb->transfer_flags |= USB_ASYNC_UNLINK | USB_NO_FSBR; +#ifdef REALLY_QUEUE + urb->transfer_flags |= USB_QUEUE_BULK; +#endif + // FIXME urb->timeout = ... jiffies ... ; + + spin_lock_irqsave (&dev->txq.lock, flags); + if (info->flags & FLAG_FRAMING) { + header->packet_id = cpu_to_le16 (dev->packet_id++); + put_unaligned (header->packet_id, &trailer->packet_id); +#if 0 + devdbg (dev, "frame >tx h %d p %d id %d", + header->hdr_len, header->packet_len, + header->packet_id); +#endif + } + + netif_stop_queue (net); + if ((retval = usb_submit_urb (urb)) != 0) { + netif_start_queue (net); + dbg ("%s tx: submit urb err %d", net->name, retval); + } else { + net->trans_start = jiffies; + __skb_queue_tail (&dev->txq, skb); + if (dev->txq.qlen < TX_QLEN) + netif_start_queue (net); + } + spin_unlock_irqrestore (&dev->txq.lock, flags); + + if (retval) { + devdbg (dev, "drop, code %d", retval); +drop: + retval = NET_XMIT_DROP; + dev->stats.tx_dropped++; + dev_kfree_skb_any (skb); + usb_free_urb (urb); +#ifdef VERBOSE + } else { + devdbg (dev, "> tx, len %d, type 0x%x", + length, skb->protocol); +#endif + } + return retval; +} + + +/*-------------------------------------------------------------------------*/ + +// tasklet ... work that avoided running in_irq() + +static void usbnet_bh (unsigned long param) +{ + struct usbnet *dev = (struct usbnet *) param; + struct sk_buff *skb; + struct skb_data *entry; + + while ((skb = skb_dequeue (&dev->done))) { + entry = (struct skb_data *) skb->cb; + switch (entry->state) { + case rx_done: + entry->state = rx_cleanup; + rx_process (dev, skb); + continue; + case tx_done: + if (entry->urb->status) { + // can this statistic become more specific? + dev->stats.tx_errors++; + dbg ("%s tx: err %d", dev->net.name, + entry->urb->status); + } else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += entry->length; + } + // FALLTHROUGH: + case rx_cleanup: + usb_free_urb (entry->urb); + dev_kfree_skb (skb); + continue; + default: + dbg ("%s: bogus skb state %d", + dev->net.name, entry->state); + } + } + + // waiting for all pending urbs to complete? + if (dev->wait) { + if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { + wake_up (dev->wait); + } + + // or are we maybe short a few urbs? + } else if (netif_running (&dev->net)) { + int temp = dev->rxq.qlen; + + if (temp < RX_QLEN) { + struct urb *urb; + int i; + for (i = 0; i < 3 && dev->rxq.qlen < RX_QLEN; i++) { + if ((urb = usb_alloc_urb (0)) != 0) + rx_submit (dev, urb, GFP_ATOMIC); + } + if (temp != dev->rxq.qlen) + devdbg (dev, "rxqlen %d --> %d", + temp, dev->rxq.qlen); + if (dev->rxq.qlen < RX_QLEN) + tasklet_schedule (&dev->bh); + } + if (dev->txq.qlen < TX_QLEN) + netif_wake_queue (&dev->net); + } +} + + + +/*------------------------------------------------------------------------- + * + * USB Device Driver support + * + *-------------------------------------------------------------------------*/ + +// precondition: never called in_interrupt + +static void usbnet_disconnect (struct usb_device *udev, void *ptr) +{ + struct usbnet *dev = (struct usbnet *) ptr; + + devinfo (dev, "unregister usbnet %03d/%03d, %s", + udev->bus->busnum, udev->devnum, + dev->driver_info->description); + + unregister_netdev (&dev->net); + + mutex_lock (&usbnet_mutex); + mutex_lock (&dev->mutex); + list_del (&dev->dev_list); + mutex_unlock (&usbnet_mutex); + + kfree (dev); + usb_dec_dev_use (udev); +} + + +/*-------------------------------------------------------------------------*/ + +// precondition: never called in_interrupt + +static void * +usbnet_probe (struct usb_device *udev, unsigned ifnum, + const struct usb_device_id *prod) +{ + struct usbnet *dev; + struct net_device *net; + struct usb_interface_descriptor *interface; + struct driver_info *info; + int altnum = 0; + + info = (struct driver_info *) prod->driver_info; + + // sanity check; expect dedicated interface/devices for now. + interface = &udev->actconfig->interface [ifnum].altsetting [altnum]; + if (udev->descriptor.bNumConfigurations != 1 + || udev->config[0].bNumInterfaces != 1 +// || interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC + ) { + dbg ("Bogus config info"); + return 0; + } + + if (usb_set_interface (udev, ifnum, altnum) < 0) { + err ("set_interface failed"); + return 0; + } + + // set up our own records + if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) { + dbg ("can't kmalloc dev"); + return 0; + } + memset (dev, 0, sizeof *dev); + + init_MUTEX_LOCKED (&dev->mutex); + usb_inc_dev_use (udev); + dev->udev = udev; + dev->driver_info = info; + INIT_LIST_HEAD (&dev->dev_list); + skb_queue_head_init (&dev->rxq); + skb_queue_head_init (&dev->txq); + skb_queue_head_init (&dev->done); + dev->bh.func = usbnet_bh; + dev->bh.data = (unsigned long) dev; + + // set up network interface records + net = &dev->net; + SET_MODULE_OWNER (net); + net->priv = dev; + strcpy (net->name, "usb%d"); + memcpy (net->dev_addr, node_id, sizeof node_id); + + // point-to-point link ... we always use Ethernet headers + // supports win32 interop and the bridge driver. + ether_setup (net); + + net->change_mtu = usbnet_change_mtu; + net->get_stats = usbnet_get_stats; + net->hard_start_xmit = usbnet_start_xmit; + net->open = usbnet_open; + net->stop = usbnet_stop; + net->watchdog_timeo = TX_TIMEOUT_JIFFIES; + net->tx_timeout = usbnet_tx_timeout; + + register_netdev (&dev->net); + devinfo (dev, "register usbnet %03d/%03d, %s", + udev->bus->busnum, udev->devnum, + dev->driver_info->description); + + // ok, it's ready to go. + mutex_lock (&usbnet_mutex); + list_add (&dev->dev_list, &usbnet_list); + mutex_unlock (&dev->mutex); + + // start as if the link is up + netif_device_attach (&dev->net); + + mutex_unlock (&usbnet_mutex); + return dev; +} + + +/*-------------------------------------------------------------------------*/ + +/* + * chip vendor names won't normally be on the cables, and + * may not be on the device. + */ + +static const struct usb_device_id products [] = { + +#ifdef CONFIG_USB_AN2720 +{ + USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults + driver_info: (unsigned long) &an2720_info, +}, +#endif + + +// GeneSys GL620USB (www.genesyslogic.com.tw) +// (patch exists against an older driver version) + + +#ifdef CONFIG_USB_LINUXDEV +/* + * for example, this can be a host side talk-to-PDA driver. + * this driver is NOT what runs _inside_ a Linux device !! + */ +{ + // 1183 = 0x049F, both used as hex values? + USB_DEVICE (0x049F, 0x505A), // Compaq "Itsy" + driver_info: (unsigned long) &linuxdev_info, +}, +#endif + +#ifdef CONFIG_USB_NET1080 +{ + USB_DEVICE (0x0525, 0x1080), // NetChip ref design + driver_info: (unsigned long) &net1080_info, +}, +#endif + +#ifdef CONFIG_USB_BELKIN_F5U104 +{ + USB_DEVICE (0x050d, 0x0004), // Belkin + driver_info: (unsigned long) &belkin_info, +}, { + USB_DEVICE (0x056c, 0x8100), // eTEK + driver_info: (unsigned long) &belkin_info, +}, +#endif + +#ifdef CONFIG_USB_PL2301 +{ + USB_DEVICE (0x067b, 0x0000), // PL-2301 + driver_info: (unsigned long) &prolific_info, +}, { + USB_DEVICE (0x067b, 0x0001), // PL-2302 + driver_info: (unsigned long) &prolific_info, +}, +#endif + + { }, // END +}; +MODULE_DEVICE_TABLE (usb, products); + +static struct usb_driver usbnet_driver = { + name: "usbnet", + id_table: products, + probe: usbnet_probe, + disconnect: usbnet_disconnect, +}; + +/*-------------------------------------------------------------------------*/ + +static int __init usbnet_init (void) +{ + // compiler should optimize this out + if (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data)) + BUG (); + + get_random_bytes (node_id, sizeof node_id); + node_id [0] &= 0xfe; // clear multicast bit + + if (usb_register (&usbnet_driver) < 0) + return -1; + + return 0; +} +module_init (usbnet_init); + +static void __exit usbnet_exit (void) +{ + usb_deregister (&usbnet_driver); +} +module_exit (usbnet_exit); + +MODULE_AUTHOR ("David Brownell "); +MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (Belkin, Linux, NetChip, Prolific, ...)"); diff -u --recursive --new-file v2.4.9/linux/fs/affs/Changes linux/fs/affs/Changes --- v2.4.9/linux/fs/affs/Changes Wed Jul 25 17:10:24 2001 +++ linux/fs/affs/Changes Tue Aug 28 07:11:20 2001 @@ -28,6 +28,14 @@ Please direct bug reports to: zippel@linux-m68k.org +Version 3.17 +------------ + +- locking fixes +- wrong sign in __affs_hash_dentry +- remove unnecessary check in affs_new_inode +- enable international mode for dircache fs + Version 3.16 ------------ diff -u --recursive --new-file v2.4.9/linux/fs/affs/amigaffs.c linux/fs/affs/amigaffs.c --- v2.4.9/linux/fs/affs/amigaffs.c Wed Jul 25 17:10:24 2001 +++ linux/fs/affs/amigaffs.c Tue Aug 28 07:11:20 2001 @@ -311,7 +311,7 @@ goto done_unlock; mark_buffer_dirty_inode(bh, inode); - affs_lock_dir(dir); + affs_unlock_dir(dir); if (inode->i_nlink > 1) retval = affs_remove_link(dentry); diff -u --recursive --new-file v2.4.9/linux/fs/affs/inode.c linux/fs/affs/inode.c --- v2.4.9/linux/fs/affs/inode.c Wed Jul 25 17:10:24 2001 +++ linux/fs/affs/inode.c Tue Aug 28 07:11:20 2001 @@ -300,7 +300,7 @@ u32 block; struct buffer_head *bh; - if (!dir || !(inode = get_empty_inode())) + if (!(inode = get_empty_inode())) goto err_inode; if (!(block = affs_alloc_block(dir, dir->i_ino))) diff -u --recursive --new-file v2.4.9/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.4.9/linux/fs/affs/namei.c Wed Jul 25 17:10:24 2001 +++ linux/fs/affs/namei.c Tue Aug 28 07:11:20 2001 @@ -72,7 +72,7 @@ static inline int __affs_hash_dentry(struct dentry *dentry, struct qstr *qstr, toupper_t toupper) { - const char *name = qstr->name; + const u8 *name = qstr->name; unsigned long hash; int i; @@ -448,25 +448,20 @@ if (!bh) goto done; - affs_lock_dir(old_dir); - if (old_dir != new_dir) - affs_lock_dir(new_dir); - /* Remove header from its parent directory. */ + affs_lock_dir(old_dir); retval = affs_remove_hash(old_dir, bh); + affs_unlock_dir(old_dir); if (retval) - goto done_unlock; + goto done; /* And insert it into the new directory with the new name. */ affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry); affs_fix_checksum(sb, bh); + affs_lock_dir(new_dir); retval = affs_insert_hash(new_dir, bh); - /* TODO: move it back to old_dir? */ - -done_unlock: - affs_unlock_dir(old_dir); - if (old_dir != new_dir) - affs_unlock_dir(new_dir); + affs_unlock_dir(new_dir); + /* TODO: move it back to old_dir, if error? */ done: mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); diff -u --recursive --new-file v2.4.9/linux/fs/affs/super.c linux/fs/affs/super.c --- v2.4.9/linux/fs/affs/super.c Thu Apr 19 22:57:06 2001 +++ linux/fs/affs/super.c Tue Aug 28 07:11:20 2001 @@ -355,16 +355,16 @@ switch (chksum) { case MUFS_FS: case MUFS_INTLFFS: + case MUFS_DCFFS: AFFS_SB->s_flags |= SF_MUFS; /* fall thru */ case FS_INTLFFS: + case FS_DCFFS: AFFS_SB->s_flags |= SF_INTL; break; - case MUFS_DCFFS: case MUFS_FFS: AFFS_SB->s_flags |= SF_MUFS; break; - case FS_DCFFS: case FS_FFS: break; case MUFS_OFS: diff -u --recursive --new-file v2.4.9/linux/fs/block_dev.c linux/fs/block_dev.c --- v2.4.9/linux/fs/block_dev.c Sun Aug 12 13:28:00 2001 +++ linux/fs/block_dev.c Tue Aug 28 11:00:41 2001 @@ -153,7 +153,7 @@ } buffercount=0; } - balance_dirty(dev); + balance_dirty(); if (write_error) break; } diff -u --recursive --new-file v2.4.9/linux/fs/buffer.c linux/fs/buffer.c --- v2.4.9/linux/fs/buffer.c Mon Aug 27 12:41:46 2001 +++ linux/fs/buffer.c Tue Aug 28 11:02:25 2001 @@ -796,7 +796,7 @@ static void free_more_memory(void) { - balance_dirty(NODEV); + balance_dirty(); page_launder(GFP_NOFS, 0); wakeup_bdflush(); wakeup_kswapd(); @@ -1086,7 +1086,7 @@ /* -1 -> no need to flush 0 -> async flush 1 -> sync flush (wait for I/O completion) */ -int balance_dirty_state(kdev_t dev) +static int balance_dirty_state(void) { unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit; @@ -1114,16 +1114,16 @@ * pressures on different devices - thus the (currently unused) * 'dev' parameter. */ -void balance_dirty(kdev_t dev) +void balance_dirty(void) { - int state = balance_dirty_state(dev); + int state = balance_dirty_state(); if (state < 0) return; /* If we're getting into imbalance, start write-out */ spin_lock(&lru_list_lock); - write_some_buffers(dev); + write_some_buffers(NODEV); /* * And if we're _really_ out of balance, wait for @@ -1132,7 +1132,7 @@ * This will throttle heavy writers. */ if (state > 0) { - wait_for_some_buffers(dev); + wait_for_some_buffers(NODEV); wakeup_bdflush(); } } @@ -1155,7 +1155,7 @@ { if (!atomic_set_buffer_dirty(bh)) { __mark_dirty(bh); - balance_dirty(bh->b_dev); + balance_dirty(); } } @@ -1712,7 +1712,7 @@ } if (need_balance_dirty) - balance_dirty(bh->b_dev); + balance_dirty(); /* * is this a partial write that happened to make all buffers * uptodate then we can optimize away a bogus readpage() for @@ -2448,6 +2448,8 @@ write_unlock(&hash_table_lock); spin_unlock(&lru_list_lock); if (gfp_mask & __GFP_IO) { + if (!(gfp_mask & __GFP_HIGHIO) && PageHighMem(page)) + return 0; sync_page_buffers(bh, gfp_mask); /* We waited synchronously, so we can free the buffers. */ if (gfp_mask & __GFP_WAIT) { @@ -2706,7 +2708,7 @@ CHECK_EMERGENCY_SYNC spin_lock(&lru_list_lock); - if (!write_some_buffers(NODEV) || balance_dirty_state(NODEV) < 0) { + if (!write_some_buffers(NODEV) || balance_dirty_state() < 0) { wait_for_some_buffers(NODEV); interruptible_sleep_on(&bdflush_wait); } diff -u --recursive --new-file v2.4.9/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c --- v2.4.9/linux/fs/cramfs/inode.c Wed Jul 25 17:10:24 2001 +++ linux/fs/cramfs/inode.c Mon Aug 27 07:53:49 2001 @@ -374,6 +374,7 @@ { struct inode *inode = page->mapping->host; u32 maxblock, bytes_filled; + void *pgdata; maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; bytes_filled = 0; @@ -387,15 +388,18 @@ start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); + pgdata = kmap(page); if (compr_len == 0) ; /* hole */ else - bytes_filled = cramfs_uncompress_block(page_address(page), + bytes_filled = cramfs_uncompress_block(pgdata, PAGE_CACHE_SIZE, cramfs_read(sb, start_offset, compr_len), compr_len); - } - memset(page_address(page) + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); + } else + pgdata = kmap(page); + memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); + kunmap(page); flush_dcache_page(page); SetPageUptodate(page); UnlockPage(page); diff -u --recursive --new-file v2.4.9/linux/fs/dquot.c linux/fs/dquot.c --- v2.4.9/linux/fs/dquot.c Sun Aug 12 13:28:00 2001 +++ linux/fs/dquot.c Tue Aug 28 10:56:06 2001 @@ -325,7 +325,7 @@ memset(&dquot->dq_dqb, 0, sizeof(struct dqblk)); } -static void invalidate_dquots(kdev_t dev, short type) +static void invalidate_dquots(struct super_block *sb, short type) { struct dquot *dquot, *next; int need_restart; @@ -335,12 +335,10 @@ need_restart = 0; while ((dquot = next) != NULL) { next = dquot->dq_next; - if (dquot->dq_dev != dev) + if (dquot->dq_sb != sb) continue; if (dquot->dq_type != type) continue; - if (!dquot->dq_sb) /* Already invalidated entry? */ - continue; if (dquot->dq_flags & DQ_LOCKED) { __wait_on_dquot(dquot); @@ -349,12 +347,10 @@ /* * Make sure it's still the same dquot. */ - if (dquot->dq_dev != dev) + if (dquot->dq_sb != sb) continue; if (dquot->dq_type != type) continue; - if (!dquot->dq_sb) - continue; } /* * Because inodes needn't to be the only holders of dquot @@ -1409,7 +1405,7 @@ /* Note: these are blocking operations */ remove_dquot_ref(sb, cnt); - invalidate_dquots(sb->s_dev, cnt); + invalidate_dquots(sb, cnt); /* Wait for any pending IO - remove me as soon as invalidate is more polite */ down(&dqopt->dqio_sem); diff -u --recursive --new-file v2.4.9/linux/fs/inode.c linux/fs/inode.c --- v2.4.9/linux/fs/inode.c Sun Aug 12 13:28:00 2001 +++ linux/fs/inode.c Mon Aug 27 08:22:28 2001 @@ -1049,6 +1049,7 @@ if (op && op->delete_inode) { void (*delete)(struct inode *) = op->delete_inode; + DQUOT_INIT(inode); /* s_op->delete_inode internally recalls clear_inode() */ delete(inode); } else diff -u --recursive --new-file v2.4.9/linux/fs/msdos/namei.c linux/fs/msdos/namei.c --- v2.4.9/linux/fs/msdos/namei.c Mon Aug 27 12:41:46 2001 +++ linux/fs/msdos/namei.c Tue Aug 28 10:54:43 2001 @@ -17,6 +17,8 @@ #include +#include "../fat/msbuffer.h" + #define MSDOS_DEBUG 0 #define PRINTK(x) diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/Makefile linux/fs/ntfs/Makefile --- v2.4.9/linux/fs/ntfs/Makefile Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/Makefile Tue Aug 28 06:57:18 2001 @@ -5,7 +5,7 @@ obj-y := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o obj-m := $(O_TARGET) # New version format started 3 February 2001. -EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.16\" #-DDEBUG +EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.17\" #-DDEBUG include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c --- v2.4.9/linux/fs/ntfs/attr.c Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/attr.c Tue Aug 28 06:57:18 2001 @@ -13,6 +13,7 @@ #include "attr.h" #include +#include #include "macros.h" #include "support.h" #include "util.h" @@ -148,7 +149,10 @@ "attribute non-resident. Bug!\n"); return -EINVAL; } - m = memcmp(value, a->d.data, min(int, value_len, a->size)); + m = value_len; + if (m > a->size) + m = a->size; + m = memcmp(value, a->d.data, m); if (m > 0) continue; if (m < 0) { @@ -234,7 +238,7 @@ } if (attr->d.r.runlist) { ntfs_memcpy(new, attr->d.r.runlist, attr->d.r.len - * sizeof(ntfs_runlist)); + * sizeof(ntfs_runlist)); ntfs_vfree(attr->d.r.runlist); } attr->d.r.runlist = new; @@ -250,7 +254,7 @@ } /* Extends an attribute. Another run will be added if necessary, but we try to - * extend the last run in the runlist first. + * extend the last run in the run list first. * FIXME: what if there isn't enough contiguous space, we don't create * multiple runs? * @@ -264,7 +268,8 @@ ntfs_cluster_t cluster; int clen; - if (attr->compressed || ino->record_count > 1) + if ((attr->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)) || + ino->record_count > 1) return -EOPNOTSUPP; if (attr->resident) { error = ntfs_make_attr_nonresident(ino, attr); @@ -272,7 +277,7 @@ return error; } if (*len <= attr->allocated) - return 0; /* Truely stupid things do sometimes happen. */ + return 0; /* Truly stupid things do sometimes happen. */ rl = attr->d.r.runlist; rlen = attr->d.r.len - 1; if (rlen >= 0) @@ -357,7 +362,7 @@ if (newsize == oldsize) return 0; /* FIXME: Modifying compressed attributes not supported yet. */ - if (attr->compressed) + if (attr->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)) /* FIXME: Extending is easy: just insert sparse runs. */ return -EOPNOTSUPP; if (attr->resident) { @@ -370,16 +375,18 @@ } v = attr->d.data; if (newsize) { + __s64 minsize = newsize; attr->d.data = ntfs_malloc(newsize); if (!attr->d.data) { ntfs_free(v); return -ENOMEM; } - if (newsize > oldsize) + if (newsize > oldsize) { + minsize = oldsize; ntfs_bzero((char*)attr->d.data + oldsize, newsize - oldsize); - ntfs_memcpy((char*)attr->d.data, v, - min(s64, newsize, oldsize)); + } + ntfs_memcpy((char*)attr->d.data, v, minsize); } else attr->d.data = 0; ntfs_free(v); @@ -389,6 +396,12 @@ /* Non-resident attribute. */ rl = attr->d.r.runlist; if (newsize < oldsize) { + /* + * FIXME: We might be going awfully wrong for newsize = 0, + * possibly even leaking memory really badly. But considering + * in that case there is more breakage due to -ENOTSUP stuff + * further down the code path, who cares for the moment... (AIA) + */ for (i = 0, count = 0; i < attr->d.r.len; i++) { if ((__s64)(count + rl[i].len) << clustersizebits > newsize) @@ -441,7 +454,7 @@ } int ntfs_create_attr(ntfs_inode *ino, int anum, char *aname, void *data, - int dsize, ntfs_attribute **rattr) + int dsize, ntfs_attribute **rattr) { void *name; int namelen; @@ -463,7 +476,7 @@ namelen = 0; } error = ntfs_new_attr(ino, anum, name, namelen, data, dsize, &i, - &found); + &found); if (error || found) { ntfs_free(name); return error ? error : -EEXIST; @@ -481,7 +494,8 @@ "+ 0x28) (%i)\n", attr->attrno, NTFS_GETU16(ino->attr + 0x28)); attr->resident = 1; - attr->compressed = attr->cengine = 0; + attr->flags = 0; + attr->cengine = 0; attr->size = attr->allocated = attr->initialized = dsize; /* FIXME: INDEXED information should come from $AttrDef @@ -498,7 +512,8 @@ return 0; } -/* Non-resident attributes are stored in runs (intervals of clusters). +/* + * Non-resident attributes are stored in runs (intervals of clusters). * * This function stores in the inode readable information about a non-resident * attribute. @@ -630,7 +645,7 @@ } attr = ino->attrs + i; attr->resident = NTFS_GETU8(attrdata + 8) == 0; - attr->compressed = NTFS_GETU16(attrdata + 0xC); + attr->flags = *(__u16*)(attrdata + 0xC); attr->attrno = NTFS_GETU16(attrdata + 0xE); if (attr->resident) { @@ -640,13 +655,13 @@ if (!attr->d.data) return -ENOMEM; ntfs_memcpy(attr->d.data, data, attr->size); - attr->indexed = NTFS_GETU16(attrdata + 0x16); + attr->indexed = NTFS_GETU8(attrdata + 0x16); } else { attr->allocated = NTFS_GETS64(attrdata + 0x28); attr->size = NTFS_GETS64(attrdata + 0x30); attr->initialized = NTFS_GETS64(attrdata + 0x38); attr->cengine = NTFS_GETU16(attrdata + 0x22); - if (attr->compressed) + if (attr->flags & ATTR_IS_COMPRESSED) attr->compsize = NTFS_GETS64(attrdata + 0x40); ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: " "attr->allocated = 0x%Lx, attr->size = 0x%Lx, " @@ -664,11 +679,14 @@ int ntfs_read_zero(ntfs_io *dest, int size) { + int i; char *sparse = ntfs_calloc(512); if (!sparse) return -ENOMEM; + i = 512; while (size) { - int i = min(int, size, 512); + if (i > size) + i = size; dest->fn_put(dest, sparse, i); size -= i; } @@ -683,7 +701,7 @@ int error = 0; int clustersizebits; int s_vcn, rnum, vcn, got, l1; - __s64 copied, len, chunk, offs1, l; + __s64 copied, len, chunk, offs1, l, chunk2; ntfs_cluster_t cluster, cl1; char *comp = 0, *comp1; char *decomp = 0; @@ -720,12 +738,15 @@ chunk = 0; if (cluster == (ntfs_cluster_t)-1) { /* Sparse cluster. */ - __s64 l1; + __s64 ll; + if ((len - (s_vcn - vcn)) & 15) ntfs_error("Unexpected sparse chunk size."); - l1 = chunk = min(s64, ((__s64)(vcn + len) << clustersizebits) - - offset, l); - error = ntfs_read_zero(dest, l1); + ll = ((__s64)(vcn + len) << clustersizebits) - offset; + if (ll > l) + ll = l; + chunk = ll; + error = ntfs_read_zero(dest, ll); if (error) goto out; } else if (dest->do_read) { @@ -741,14 +762,21 @@ cl1 = cluster + s_vcn - vcn; comp1 = comp; do { + int delta; + io.param = comp1; - l1 = min(int, len - max(int, s_vcn - vcn, 0), 16 - got); + delta = s_vcn - vcn; + if (delta < 0) + delta = 0; + l1 = len - delta; + if (l1 > 16 - got) + l1 = 16 - got; io.size = (__s64)l1 << clustersizebits; error = ntfs_getput_clusters(ino->vol, cl1, 0, &io); if (error) goto out; - if (l1 + max(int, s_vcn - vcn, 0) == len) { + if (l1 + delta == len) { rnum++; rl++; vcn += len; @@ -779,8 +807,11 @@ comp1 = decomp; } offs1 = offset - ((__s64)s_vcn << clustersizebits); - chunk = min(s64, (16 << clustersizebits) - offs1, chunk); - chunk = min(s64, l, chunk); + chunk2 = (16 << clustersizebits) - offs1; + if (chunk2 > l) + chunk2 = l; + if (chunk > chunk2) + chunk = chunk2; dest->fn_put(dest, comp1 + offs1, chunk); } l -= chunk; @@ -795,7 +826,7 @@ len = rl->len; } } - out: +out: if (comp) ntfs_free(comp); if (decomp) @@ -805,7 +836,7 @@ } int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset, - ntfs_io *dest) + ntfs_io *dest) { return -EOPNOTSUPP; } diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/dir.c linux/fs/ntfs/dir.c --- v2.4.9/linux/fs/ntfs/dir.c Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/dir.c Tue Aug 28 06:57:18 2001 @@ -27,8 +27,7 @@ * be restored. */ int ntfs_check_index_record(ntfs_inode *ino, char *record) { - return ntfs_fixup_record(ino->vol, record, "INDX", - ino->u.index.recordsize); + return ntfs_fixup_record(record, "INDX", ino->u.index.recordsize); } static inline int ntfs_is_top(ntfs_u64 stack) @@ -268,12 +267,21 @@ ntfs_resize_attr(walk->dir, a, used); } else { NTFS_PUTU16(buf + 0x1C, used - 0x18); - ntfs_insert_fixups(buf, vol->sector_size); io.size = walk->dir->u.index.recordsize; + error = ntfs_insert_fixups(buf, io.size); + if (error) { + printk(KERN_ALERT "NTFS: ntfs_index_writeback() caught " + "corrupt index record ntfs record " + "header. Refusing to write corrupt " + "data to disk. Unmount and run chkdsk " + "immediately!\n"); + return -EIO; + } error = ntfs_write_attr(walk->dir, vol->at_index_allocation, - I30, (__s64)block << vol->cluster_size_bits, &io); + I30, (__s64)block << vol->cluster_size_bits, + &io); if (error || (io.size != walk->dir->u.index.recordsize && - (error = -EIO, 1))) + (error = -EIO, 1))) return error; } return 0; @@ -467,7 +475,7 @@ NTFS_PUTU32(index + 0x24, NTFS_GETU32(root + 0x1C)); error = ntfs_index_writeback(&walk, index, walk.newblock, isize + NTFS_GETU16(index + 0x18) + 0x18); - if(error) + if (error) goto out; /* Mark root as split. */ NTFS_PUTU32(root + 0x1C, 1); diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c --- v2.4.9/linux/fs/ntfs/fs.c Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/fs.c Tue Aug 28 06:57:18 2001 @@ -11,7 +11,7 @@ */ #include - +#include #include "ntfstypes.h" #include "struct.h" #include "util.h" @@ -27,10 +27,8 @@ #include #include #include - -#ifndef NLS_MAX_CHARSET_SIZE #include -#endif +#include /* Forward declarations. */ static struct inode_operations ntfs_dir_inode_operations; @@ -67,6 +65,7 @@ { int error; ntfs_io io; + ntfs_attribute *attr; ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode); /* Inode is not properly initialized. */ @@ -75,11 +74,14 @@ ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->", (unsigned)ino->i_number, (unsigned long long)*off, (unsigned)count); + attr = ntfs_find_attr(ino, ino->vol->at_data, NULL); /* Inode has no unnamed data attribute. */ - if(!ntfs_find_attr(ino, ino->vol->at_data, NULL)) { + if (!attr) { ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!\n"); return -EINVAL; } + if (attr->flags & ATTR_IS_ENCRYPTED) + return -EACCES; /* Read the data. */ io.fn_put = ntfs_putuser; io.fn_get = 0; @@ -285,8 +287,21 @@ return 1; } +/* + * This needs to be outside parse_options() otherwise a remount will reset + * these unintentionally. + */ +static void init_ntfs_super_block(ntfs_volume* vol) +{ + vol->uid = vol->gid = 0; + vol->umask = 0077; + vol->ngt = ngt_nt; + vol->nls_map = (void*)-1; + vol->mft_zone_multiplier = -1; +} + /* Parse the (re)mount options. */ -static int parse_options(ntfs_volume *vol, char *opt, int remount) +static int parse_options(ntfs_volume *vol, char *opt) { char *value; /* Defaults if not specified and !remount. */ ntfs_uid_t uid = -1; /* 0, root user only */ @@ -296,6 +311,8 @@ void *nls_map = NULL; /* Try to load the default NLS. */ int use_utf8 = -1; /* If no NLS specified and loading the default NLS failed use utf8. */ + int mft_zone_mul = -1; /* 1 */ + if (!opt) goto done; for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) { @@ -326,6 +343,24 @@ "argument\n"); return 0; } + } else if (strcmp(opt, "mft_zone_multiplier") == 0) { + unsigned long ul; + + if (!value || !*value) + goto needs_arg; + ul = simple_strtoul(value, &value, 0); + if (*value) { + printk(KERN_ERR "NTFS: mft_zone_multiplier " + "invalid argument\n"); + return 0; + } + if (ul >= 1 && ul <= 4) + mft_zone_mul = ul; + else { + mft_zone_mul = 1; + printk(KERN_WARNING "NTFS: mft_zone_multiplier " + "out of range. Setting to 1.\n"); + } } else if (strcmp(opt, "posix") == 0) { int val; if (!value || !*value) @@ -361,40 +396,69 @@ } } done: - if (use_utf8 != -1 && use_utf8) { - if (nls_map) { + if (use_utf8 == -1) { + /* utf8 was not specified at all. */ + if (!nls_map) { + /* + * No NLS was specified. If first mount, load the + * default NLS, otherwise don't change the NLS setting. + */ + if (vol->nls_map == (void*)-1) + vol->nls_map = load_nls_default(); + } else { + /* If an NLS was already loaded, unload it first. */ + if (vol->nls_map && vol->nls_map != (void*)-1) + unload_nls(vol->nls_map); + /* Use the specified NLS. */ + vol->nls_map = nls_map; + } + } else { + /* utf8 was specified. */ + if (use_utf8 && nls_map) { unload_nls(nls_map); printk(KERN_ERR "NTFS: utf8 cannot be combined with " "iocharset.\n"); return 0; } - if (remount && vol->nls_map) + /* If an NLS was already loaded, unload it first. */ + if (vol->nls_map && vol->nls_map != (void*)-1) unload_nls(vol->nls_map); - vol->nls_map = NULL; - } else { - if (nls_map) { - if (remount && vol->nls_map) - unload_nls(vol->nls_map); - vol->nls_map = nls_map; - } else if (!remount || (remount && !use_utf8 && !vol->nls_map)) - vol->nls_map = load_nls_default(); + if (!use_utf8) { + /* utf8 was specified as false. */ + if (!nls_map) + /* No NLS was specified, load the default. */ + vol->nls_map = load_nls_default(); + else + /* Use the specified NLS. */ + vol->nls_map = nls_map; + } else + /* utf8 was specified as true. */ + vol->nls_map = NULL; } if (uid != -1) vol->uid = uid; - else if (!remount) - vol->uid = 0; if (gid != -1) vol->gid = gid; - else if (!remount) - vol->gid = 0; if (umask != -1) vol->umask = (ntmode_t)umask; - else if (!remount) - vol->umask = 0077; if (ngt != -1) vol->ngt = ngt; - else if (!remount) - vol->ngt = ngt_nt; + if (mft_zone_mul != -1) { + /* mft_zone_multiplier was specified. */ + if (vol->mft_zone_multiplier != -1) { + /* This is a remount, ignore a change and warn user. */ + if (vol->mft_zone_multiplier != mft_zone_mul) + printk(KERN_WARNING "NTFS: Ignoring changes in " + "mft_zone_multiplier on " + "remount. If you want to " + "change this you need to " + "umount and mount again.\n"); + } else + /* Use the specified multiplier. */ + vol->mft_zone_multiplier = mft_zone_mul; + } else if (vol->mft_zone_multiplier == -1) + /* No multiplier specified and first mount, so set default. */ + vol->mft_zone_multiplier = 1; return 1; needs_arg: printk(KERN_ERR "NTFS: %s needs an argument", opt); @@ -436,10 +500,12 @@ } static struct file_operations ntfs_file_operations_nommap = { + llseek: generic_file_llseek, read: ntfs_read, #ifdef CONFIG_NTFS_RW write: ntfs_write, #endif + open: generic_file_open, }; static struct inode_operations ntfs_inode_operations_nobmap; @@ -556,18 +622,8 @@ } #endif -#if 0 -static int ntfs_bmap(struct inode *ino, int block) -{ - int ret = ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino), block); - ntfs_debug(DEBUG_OTHER, "bmap of %lx, block %x is %x\n", ino->i_ino, - block, ret); - return (ret == -1) ? 0 : ret; -} -#endif - /* It's fscking broken. */ -/* FIXME: [bm]map code is disabled until ntfs_get_block() gets sorted! */ +/* FIXME: mmap code is disabled until ntfs_get_block() gets sorted! */ /* static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create) { @@ -576,11 +632,13 @@ } static struct file_operations ntfs_file_operations = { + llseek: generic_file_llseek, read: ntfs_read, mmap: generic_file_mmap, #ifdef CONFIG_NTFS_RW write: ntfs_write, #endif + open: generic_file_open, }; static struct inode_operations ntfs_inode_operations; @@ -646,19 +704,10 @@ vol = NTFS_INO2VOL(inode); inode->i_mode = 0; - ntfs_debug(DEBUG_OTHER, "ntfs_read_inode 0x%x\n", (unsigned)inode->i_ino); - /* - * This kills all accesses to system files (except $Extend directory). - * The driver can bypass this by calling ntfs_init_inode() directly. - * Only if ngt is ngt_full do we allow access to the system files. - */ + ntfs_debug(DEBUG_OTHER, "ntfs_read_inode 0x%lx\n", inode->i_ino); switch (inode->i_ino) { /* Those are loaded special files. */ case FILE_$Mft: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to open $MFT!\n"); - return; - } if (!vol->mft_ino || ((vol->ino_flags & 1) == 0)) goto sys_file_error; ntfs_memcpy(&inode->u.ntfs_i, vol->mft_ino, sizeof(ntfs_inode)); @@ -670,10 +719,6 @@ ntfs_debug(DEBUG_OTHER, "Opening $MFT!\n"); break; case FILE_$MftMirr: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to open $MFTMirr!\n"); - return; - } if (!vol->mftmirr || ((vol->ino_flags & 2) == 0)) goto sys_file_error; ntfs_memcpy(&inode->u.ntfs_i, vol->mftmirr, sizeof(ntfs_inode)); @@ -685,10 +730,6 @@ ntfs_debug(DEBUG_OTHER, "Opening $MFTMirr!\n"); break; case FILE_$BitMap: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to open $Bitmap!\n"); - return; - } if (!vol->bitmap || ((vol->ino_flags & 4) == 0)) goto sys_file_error; ntfs_memcpy(&inode->u.ntfs_i, vol->bitmap, sizeof(ntfs_inode)); @@ -700,14 +741,10 @@ ntfs_debug(DEBUG_OTHER, "Opening $Bitmap!\n"); break; case FILE_$LogFile ... FILE_$AttrDef: - /* We need to allow reading the root directory. */ + /* No need to log root directory accesses. */ case FILE_$Boot ... FILE_$UpCase: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to open system file %i!\n", - inode->i_ino); - return; - } /* Do the default for ngt_full. */ - ntfs_debug(DEBUG_OTHER, "Opening system file %i!\n", inode->i_ino); + ntfs_debug(DEBUG_OTHER, "Opening system file %i!\n", + inode->i_ino); default: ino = &inode->u.ntfs_i; if (!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode), @@ -731,7 +768,8 @@ inode->i_size = data->size; /* FIXME: once ntfs_get_block is implemented, uncomment the * next line and remove the "can_mmap = 0;". (AIA) */ - /* can_mmap = !data->resident && !data->compressed; */ + /* can_mmap = !data->resident && !(data->flags & + * (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)); */ can_mmap = 0; } /* Get the file modification times from the standard information. */ @@ -768,7 +806,7 @@ inode->i_mode = S_IFREG | S_IRUGO; } #ifdef CONFIG_NTFS_RW - if (!data || !data->compressed) + if (!data || !(data->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED))) inode->i_mode |= S_IWUGO; #endif inode->i_mode &= ~vol->umask; @@ -798,13 +836,10 @@ ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%x\n", inode->i_ino); vol = NTFS_INO2VOL(inode); if (!vol) - ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is NULL.\n"); + ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is " + "NULL.\n"); switch (inode->i_ino) { case FILE_$Mft: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to _clear_inode of $MFT!\n"); - goto unl_out; - } if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) { ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode)); @@ -814,10 +849,6 @@ } break; case FILE_$MftMirr: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to _clear_inode of $MFTMirr!\n"); - goto unl_out; - } if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) { ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode)); @@ -827,10 +858,6 @@ } break; case FILE_$BitMap: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to _clear_inode of $Bitmap!\n"); - goto unl_out; - } if (vol->bitmap && ((vol->ino_flags & 4) == 0)) { ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode)); @@ -839,13 +866,6 @@ goto unl_out; } break; - case FILE_$LogFile ... FILE_$AttrDef: - case FILE_$Boot ... FILE_$UpCase: - if (vol->ngt != ngt_full) { - ntfs_error("Trying to _clear_inode of system file %i! " - "Shouldn't happen.\n", inode->i_ino); - goto unl_out; - } /* Do the default for ngt_full. */ default: /* Nothing. Just clear the inode and exit. */ } @@ -905,7 +925,7 @@ /* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */ static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options) { - if (!parse_options(NTFS_SB2VOL(sb), options, 1)) + if (!parse_options(NTFS_SB2VOL(sb), options)) return -EINVAL; return 0; } @@ -1006,11 +1026,12 @@ { ntfs_volume *vol; struct buffer_head *bh; - int i; + int i, to_read; ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n"); vol = NTFS_SB2VOL(sb); - if (!parse_options(vol, (char*)options, 0)) + init_ntfs_super_block(vol); + if (!parse_options(vol, (char*)options)) goto ntfs_read_super_vol; /* Assume a 512 bytes block device for now. */ set_blocksize(sb->s_dev, 512); @@ -1048,12 +1069,17 @@ set_blocksize(sb->s_dev, sb->s_blocksize); ntfs_debug(DEBUG_OTHER, "set_blocksize\n"); /* Allocate an MFT record (MFT record can be smaller than a cluster). */ - if (!(vol->mft = ntfs_malloc(max(int, vol->mft_record_size, - vol->cluster_size)))) + i = vol->cluster_size; + if (i < vol->mft_record_size) + i = vol->mft_record_size; + if (!(vol->mft = ntfs_malloc(i))) goto ntfs_read_super_unl; /* Read at least the MFT record for $Mft. */ - for (i = 0; i < max(int, vol->mft_clusters_per_record, 1); i++) { + to_read = vol->mft_clusters_per_record; + if (to_read < 1) + to_read = 1; + for (i = 0; i < to_read; i++) { if (!(bh = bread(sb->s_dev, vol->mft_lcn + i, vol->cluster_size))) { ntfs_error("Could not read $Mft record 0\n"); diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c --- v2.4.9/linux/fs/ntfs/inode.c Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/inode.c Tue Aug 28 06:57:18 2001 @@ -20,6 +20,7 @@ #include "dir.h" #include "support.h" #include "util.h" +#include #include typedef struct { @@ -88,7 +89,7 @@ /* Try to allocate at least 0.1% of the remaining disk space for * inodes. If the disk is almost full, make sure at least one inode is * requested. */ - int rcount, error, block, blockbits; + int rcount, error, mft_rec_size; __s64 size; ntfs_attribute *mdata, *bmp; ntfs_u8 *buf; @@ -97,35 +98,34 @@ mdata = ntfs_find_attr(vol->mft_ino, vol->at_data, 0); if (!mdata) return -EINVAL; + mft_rec_size = vol->mft_record_size; /* First check whether there is uninitialized space. */ - if (mdata->allocated < mdata->size + vol->mft_record_size) { + if (mdata->allocated < mdata->size + mft_rec_size) { size = (__s64)ntfs_get_free_cluster_count(vol->bitmap) << - vol->cluster_size_bits; + vol->cluster_size_bits >> 10; /* On error, size will be negative. We can ignore this as we * will fall back to the minimal size allocation below. (AIA) */ - block = vol->mft_record_size; - blockbits = vol->mft_record_size_bits; - size = max(s64, size >> 10, mdata->size + vol->mft_record_size); - size = (__s64)((size + block - 1) >> blockbits) << blockbits; - /* Require this to be a single chunk. */ + if (size < mdata->size + mft_rec_size) + size = mdata->size + mft_rec_size; + size += mft_rec_size - 1; + size &= ~(__s64)(mft_rec_size - 1); error = ntfs_extend_attr(vol->mft_ino, mdata, &size, - ALLOC_REQUIRE_SIZE); + ALLOC_REQUIRE_SIZE); /* Try again, now we have the largest available fragment. */ if (error == -ENOSPC) { /* Round down to multiple of mft record size. */ - size = (__s64)(size >> vol->mft_record_size_bits) << - vol->mft_record_size_bits; + size &= ~(__s64)(mft_rec_size - 1); if (!size) return -ENOSPC; error = ntfs_extend_attr(vol->mft_ino, mdata, &size, - ALLOC_REQUIRE_SIZE); + ALLOC_REQUIRE_SIZE); } if (error) return error; } /* Even though we might have allocated more than needed, we initialize * only one record. */ - mdata->size += vol->mft_record_size; + mdata->size += mft_rec_size; /* Now extend the bitmap if necessary. */ rcount = mdata->size >> vol->mft_record_size_bits; bmp = ntfs_find_attr(vol->mft_ino, vol->at_bitmap, 0); @@ -144,27 +144,34 @@ io.param = buf; io.size = 1; error = ntfs_write_attr(vol->mft_ino, vol->at_bitmap, 0, - bmp->size - 1, &io); + bmp->size - 1, &io); if (error) return error; if (io.size != 1) return -EIO; } /* Now fill in the MFT header for the new block. */ - buf = ntfs_calloc(vol->mft_record_size); + buf = ntfs_calloc(mft_rec_size); if (!buf) return -ENOMEM; - ntfs_fill_mft_header(buf, vol->mft_record_size, vol->sector_size, 0); - ntfs_insert_fixups(buf, vol->sector_size); + ntfs_fill_mft_header(buf, mft_rec_size, vol->sector_size, 0); + error = ntfs_insert_fixups(buf, mft_rec_size); + if (error) { + printk(KERN_ALERT "NTFS: ntfs_extend_mft() caught corrupt " + "mtf record ntfs record header. Refusing to " + "write corrupt data to disk. Unmount and run " + "chkdsk immediately!\n"); + return -EIO; + } io.param = buf; - io.size = vol->mft_record_size; + io.size = mft_rec_size; io.fn_put = ntfs_put; io.fn_get = ntfs_get; error = ntfs_write_attr(vol->mft_ino, vol->at_data, 0, (__s64)(rcount - 1) << vol->mft_record_size_bits, &io); if (error) return error; - if (io.size != vol->mft_record_size) + if (io.size != mft_rec_size) return -EIO; error = ntfs_update_inode(vol->mft_ino); if (error) @@ -394,11 +401,14 @@ io.fn_put = ntfs_put; io.fn_get = 0; io.param = buf + delta; - io.size = len = min(int, datasize, 1024 - delta); + len = 1024 - delta; + if (len > datasize) + len = datasize; ntfs_debug(DEBUG_FILE2, "load_attributes %x: len = %i\n", ino->i_number, len); ntfs_debug(DEBUG_FILE2, "load_attributes %x: delta = %i\n", ino->i_number, delta); + io.size = len; if (ntfs_read_attr(ino, vol->at_attribute_list, 0, offset, &io)) ntfs_error("error in load_attributes\n"); @@ -472,7 +482,7 @@ /* Check and fixup a MFT record. */ int ntfs_check_mft_record(ntfs_volume *vol, char *record) { - return ntfs_fixup_record(vol, record, "FILE", vol->mft_record_size); + return ntfs_fixup_record(record, "FILE", vol->mft_record_size); } /* Return (in result) the value indicating the next available attribute @@ -540,8 +550,7 @@ ntfs_attribute *attr = ntfs_find_attr(ino, type, name); if (!attr) return 0; - return - attr->resident; + return attr->resident; } /* @@ -702,10 +711,10 @@ return error; return ntfs_read_zero(dest, l - chunk); } - if (attr->compressed) + if (attr->flags & ATTR_IS_COMPRESSED) return ntfs_read_compressed(ino, attr, offset, dest); } else { - if (attr->compressed) + if (attr->flags & ATTR_IS_COMPRESSED) return ntfs_write_compressed(ino, attr, offset, dest); } vcn = 0; @@ -720,7 +729,7 @@ "inode = 0x%x, rnum = %i, offset = 0x%Lx, vcn = , 0x%x" "s_vcn = 0x%x\n", ino->i_number, rnum, offset, vcn, s_vcn); - /*FIXME: Should extend runlist. */ + /*FIXME: Should extend run list. */ return -EOPNOTSUPP; } copied = 0; @@ -729,8 +738,9 @@ cluster = attr->d.r.runlist[rnum].cluster; len = attr->d.r.runlist[rnum].len; s_cluster = cluster + s_vcn - vcn; - chunk = min(s64, ((__s64)(vcn + len) << clustersizebits) - offset, - l); + chunk = ((__s64)(vcn + len) << clustersizebits) - offset; + if (chunk > l) + chunk = l; dest->size = chunk; error = ntfs_getput_clusters(ino->vol, s_cluster, offset - ((__s64)s_vcn << clustersizebits), dest); @@ -787,7 +797,8 @@ data = ntfs_find_attr(ino, ino->vol->at_data, 0); /* It's hard to give an error code. */ - if (!data || data->resident || data->compressed) + if (!data || data->resident || data->flags & (ATTR_IS_COMPRESSED | + ATTR_IS_ENCRYPTED)) return -1; if (data->size <= (__s64)vcn << ino->vol->cluster_size_bits) return -1; @@ -845,15 +856,15 @@ } /** - * layout_runs - compress runlist into mapping pairs array - * @attr: attribute containing the runlist to compress + * layout_runs - compress run list into mapping pairs array + * @attr: attribute containing the run list to compress * @rec: destination buffer to hold the mapping pairs array * @offs: current position in @rec (in/out variable) * @size: size of the buffer @rec * - * layout_runs walks the runlist in @attr, compresses it and writes it out the + * layout_runs walks the run list in @attr, compresses it and writes it out the * resulting mapping pairs array into @rec (up to a maximum of @size bytes are - * written). On entry @offs is the offset in @rec at which to begin writting the + * written). On entry @offs is the offset in @rec at which to begin writing the * mapping pairs array. On exit, it contains the offset in @rec of the first * byte after the end of the mapping pairs array. */ @@ -997,14 +1008,14 @@ if (size < asize) return -E2BIG; NTFS_PUTU32(buf + 0x10, attr->size); - NTFS_PUTU16(buf + 0x16, attr->indexed); + NTFS_PUTU8(buf + 0x16, attr->indexed); NTFS_PUTU16(buf + 0x14, hdrsize); if (attr->size) ntfs_memcpy(buf + hdrsize, attr->d.data, attr->size); } else { int error; - if (attr->compressed) + if (attr->flags & ATTR_IS_COMPRESSED) nameoff = 0x48; else nameoff = 0x40; @@ -1029,7 +1040,7 @@ NTFS_PUTS64(buf + 0x28, attr->allocated); NTFS_PUTS64(buf + 0x30, attr->size); NTFS_PUTS64(buf + 0x38, attr->initialized); - if (attr->compressed) + if (attr->flags & ATTR_IS_COMPRESSED) NTFS_PUTS64(buf + 0x40, attr->compsize); } NTFS_PUTU32(buf, attr->type); @@ -1037,7 +1048,7 @@ NTFS_PUTU8(buf + 8, attr->resident ? 0 : 1); NTFS_PUTU8(buf + 9, attr->namelen); NTFS_PUTU16(buf + 0xa, nameoff); - NTFS_PUTU16(buf + 0xc, attr->compressed); + NTFS_PUTU16(buf + 0xc, attr->flags); NTFS_PUTU16(buf + 0xe, attr->attrno); if (attr->namelen) ntfs_memcpy(buf + nameoff, attr->name, 2 * attr->namelen); @@ -1151,14 +1162,24 @@ io.fn_get = ntfs_get; io.fn_put = 0; for (i = 0; i < store.count; i++) { - ntfs_insert_fixups(store.records[i].record, - ino->vol->sector_size); + error = ntfs_insert_fixups(store.records[i].record, + ino->vol->mft_record_size); + if (error) { + printk(KERN_ALERT "NTFS: ntfs_update_inode() caught " + "corrupt %s mtf record ntfs record " + "header. Refusing to write corrupt " + "data to disk. Unmount and run chkdsk " + "immediately!\n", i ? "extension": + "base"); + deallocate_store(&store); + return -EIO; + } io.param = store.records[i].record; io.size = ino->vol->mft_record_size; /* FIXME: Is this the right way? */ error = ntfs_write_attr(ino->vol->mft_ino, ino->vol->at_data, - 0, (__s64)store.records[i].recno << - ino->vol->mft_record_size_bits, &io); + 0, (__s64)store.records[i].recno << + ino->vol->mft_record_size_bits, &io); if (error || io.size != ino->vol->mft_record_size) { /* Big trouble, partially written file. */ ntfs_error("Please unmount: Write error in inode " diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/struct.h linux/fs/ntfs/struct.h --- v2.4.9/linux/fs/ntfs/struct.h Wed Jul 25 17:10:24 2001 +++ linux/fs/ntfs/struct.h Tue Aug 28 06:57:18 2001 @@ -4,6 +4,7 @@ * Copyright (C) 1997 Régis Duchesne * Copyright (C) 2000-2001 Anton Altaparmakov (AIA) */ +#include /* Necessary forward definition. */ struct ntfs_inode; @@ -28,7 +29,8 @@ int namelen; int attrno; __s64 size, allocated, initialized, compsize; - int compressed, resident, indexed; + ATTR_FLAGS flags; + __u8 resident, indexed; int cengine; union { void *data; /* if resident */ diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/super.c linux/fs/ntfs/super.c --- v2.4.9/linux/fs/ntfs/super.c Wed Jul 25 17:10:24 2001 +++ linux/fs/ntfs/super.c Tue Aug 28 06:57:18 2001 @@ -7,16 +7,18 @@ * Copyright (C) 2000-2001 Anton Altparmakov (AIA) */ +#include +#include +#include +#include #include "ntfstypes.h" #include "struct.h" #include "super.h" - -#include -#include #include "macros.h" #include "inode.h" #include "support.h" #include "util.h" +#include /* All important structures in NTFS use 2 consistency checks: * . a magic structure identifier (FILE, INDX, RSTR, RCRD...) @@ -24,14 +26,18 @@ * structure's record should end with the word at offset of the first * sector, and if it is the case, must be replaced with the words following * . The value of and the number of fixups is taken from the fields - * at the offsets 4 and 6. + * at the offsets 4 and 6. Note that the sector size is defined as + * NTFS_SECTOR_SIZE and not as the hardware sector size (this is concordant + * with what the Windows NTFS driver does). * - * This function perform these 2 checks, and _fails_ if : + * This function perform these 2 checks, and _fails_ if: + * . the input size is invalid + * . the fixup header is invalid + * . the size does not match the number of sectors * . the magic identifier is wrong - * . the size is given and does not match the number of sectors * . a fixup is invalid */ -int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size) +int ntfs_fixup_record(char *record, char *magic, int size) { int start, count, offset; ntfs_u16 fixup; @@ -39,19 +45,24 @@ if (!IS_MAGIC(record, magic)) return 0; start = NTFS_GETU16(record + 4); - count = NTFS_GETU16(record + 6); - count--; - if(size && vol->sector_size * count != size) + count = NTFS_GETU16(record + 6) - 1; + if (size & (NTFS_SECTOR_SIZE - 1) || start & 1 || + start + count * 2 > size || size >> 9 != count) { + if (size <= 0) + printk(KERN_ERR "NTFS: BUG: ntfs_fixup_record() got " + "zero size! Please report this to " + "linux-ntfs-dev@lists.sf.net\n"); return 0; + } fixup = NTFS_GETU16(record + start); start += 2; - offset = vol->sector_size - 2; - while (count--){ + offset = NTFS_SECTOR_SIZE - 2; + while (count--) { if (NTFS_GETU16(record + offset) != fixup) return 0; NTFS_PUTU16(record + offset, NTFS_GETU16(record + start)); start += 2; - offset += vol->sector_size; + offset += NTFS_SECTOR_SIZE; } return 1; } @@ -63,8 +74,9 @@ int ntfs_init_volume(ntfs_volume *vol, char *boot) { int sectors_per_cluster_bits; + __s64 ll; - /* Historical default values, in case we don't load $AttrDef. */ + /* System defined default values, in case we don't load $AttrDef. */ vol->at_standard_information = 0x10; vol->at_attribute_list = 0x20; vol->at_file_name = 0x30; @@ -77,7 +89,7 @@ vol->at_index_allocation = 0xA0; vol->at_bitmap = 0xB0; vol->at_symlink = 0xC0; - /* Sector size */ + /* Sector size. */ vol->sector_size = NTFS_GETU16(boot + 0xB); ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->sector_size = 0x%x\n", vol->sector_size); @@ -127,22 +139,49 @@ vol->index_record_size = 1 << -vol->index_clusters_per_record; vol->index_record_size_bits = ffs(vol->index_record_size) - 1; ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size = " - "0x%x\n", vol->index_record_size); + "0x%x\n", vol->index_record_size); ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size_bits " - "= 0x%x\n", vol->index_record_size_bits); + "= 0x%x\n", vol->index_record_size_bits); /* - * Check mft and mftmirr locations for 64-bit-ness. NOTE: This is a - * crude check only as many other things could be out of bounds later - * on, but it will catch at least some of the cases, since the mftmirr - * is located in the middle of the volume so if the volume is very - * large the mftmirr probably will be out of 32-bit bounds. + * Get the size of the volume in clusters (ofs 0x28 is nr_sectors) and + * check for 64-bit-ness. Windows currently only uses 32 bits to save + * the clusters so we do the same as it is much faster on 32-bit CPUs. */ - vol->mft_lcn = NTFS_GETS64(boot + 0x30); - if (vol->mft_lcn >= (__s64)1 << 31 || - NTFS_GETS64(boot + 0x38) >= (__s64)1 << 31) { - ntfs_error("Cannot handle 64-bit clusters yet.\n"); + ll = NTFS_GETS64(boot + 0x28) >> sectors_per_cluster_bits; + if (ll >= (__s64)1 << 31) { + ntfs_error("Cannot handle 64-bit clusters. Please inform " + "linux-ntfs-dev@lists.sf.net that you got this " + "error.\n"); return -1; } + vol->nr_clusters = (ntfs_cluster_t)ll; + ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->nr_clusters = 0x%x\n", + vol->nr_clusters); + /* + * Determine MFT zone size. FIXME: Need to take into consideration + * where the mft zone starts (at vol->mft_lcn) as vol->mft_zone_end + * needs to be relative to that. + */ + vol->mft_zone_end = vol->nr_clusters; + switch (vol->mft_zone_multiplier) { /* % of volume size in clusters */ + case 4: + vol->mft_zone_end = vol->mft_zone_end >> 1; /* 50% */ + break; + case 3: + vol->mft_zone_end = vol->mft_zone_end * 3 >> 3; /* 37.5% */ + break; + case 2: + vol->mft_zone_end = vol->mft_zone_end >> 2; /* 25% */ + break; + /* case 1: */ + default: + vol->mft_zone_end = vol->mft_zone_end >> 3; /* 12.5% */ + break; + } + ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_zone_end = %x\n", + vol->mft_zone_end); + vol->mft_lcn = (ntfs_cluster_t)NTFS_GETS64(boot + 0x30); + vol->mft_mirr_lcn = (ntfs_cluster_t)NTFS_GETS64(boot + 0x38); /* This will be initialized later. */ vol->upcase = 0; vol->upcase_length = 0; @@ -304,8 +343,7 @@ error = -ENOMEM; ntfs_debug(DEBUG_BSD, "Going to load MFT\n"); if (!vol->mft_ino || (error = ntfs_init_inode(vol->mft_ino, vol, - FILE_$Mft))) - { + FILE_$Mft))) { ntfs_error("Problem loading MFT\n"); return error; } @@ -443,26 +481,48 @@ return clusters; } -/* Insert the fixups for the record. The number and location of the fixes - * is obtained from the record header */ -void ntfs_insert_fixups(unsigned char *rec, int secsize) +/* + * Insert the fixups for the record. The number and location of the fixes + * is obtained from the record header but we double check with @rec_size and + * use that as the upper boundary, if necessary overwriting the count value in + * the record header. + * + * We return 0 on success or -1 if fixup header indicated the beginning of the + * update sequence array to be beyond the valid limit. + */ +int ntfs_insert_fixups(unsigned char *rec, int rec_size) { - int first = NTFS_GETU16(rec + 4); - int count = NTFS_GETU16(rec + 6); + int first; + int count; int offset = -2; - ntfs_u16 fix = NTFS_GETU16(rec + first); + ntfs_u16 fix; - fix++; + first = NTFS_GETU16(rec + 4); + count = (rec_size >> NTFS_SECTOR_BITS) + 1; + if (first + count * 2 > NTFS_SECTOR_SIZE - 2) { + printk(KERN_CRIT "NTFS: ntfs_insert_fixups() detected corrupt " + "NTFS record update sequence array position. - " + "Cannot hotfix.\n"); + return -1; + } + if (count != NTFS_GETU16(rec + 6)) { + printk(KERN_ERR "NTFS: ntfs_insert_fixups() detected corrupt " + "NTFS record update sequence array size. - " + "Applying hotfix.\n"); + NTFS_PUTU16(rec + 6, count); + } + fix = (NTFS_GETU16(rec + first) + 1) & 0xffff; if (fix == 0xffff || !fix) fix = 1; NTFS_PUTU16(rec + first, fix); count--; while (count--) { first += 2; - offset += secsize; + offset += NTFS_SECTOR_SIZE; NTFS_PUTU16(rec + first, NTFS_GETU16(rec + offset)); NTFS_PUTU16(rec + offset, fix); - }; + } + return 0; } /* Search the bitmap bits of l bytes for *cnt zero bits. Return the bit number @@ -475,7 +535,7 @@ int bc = 0; int bstart = 0, bstop = 0, found = 0; int start, stop = 0, in = 0; - /* special case searching for a single block */ + /* Special case searching for a single block. */ if (*cnt == 1) { while (l && *bits == 0xFF) { bits++; @@ -501,7 +561,7 @@ if (in) { if ((c & 1) == 0) stop++; - else { /* end of sequence of zeroes */ + else { /* End of sequence of zeroes. */ in = 0; if (!found || bstop-bstart < stop-start) { bstop = stop; bstart = start; @@ -514,7 +574,7 @@ } else { if (c & 1) start++; - else { /*start of sequence*/ + else { /* Start of sequence. */ in = 1; stop = start + 1; } @@ -523,7 +583,9 @@ c >>= 1; } if (in && (!found || bstop - bstart < stop - start)) { - bstop = stop; bstart = start; found = 1; + bstop = stop; + bstart = start; + found = 1; } if (!found) return -ENOSPC; @@ -541,21 +603,21 @@ io.fn_put = ntfs_put; io.fn_get = ntfs_get; - bsize = (cnt + (loc & 7) + 7) >> 3; /* round up to multiple of 8*/ + bsize = (cnt + (loc & 7) + 7) >> 3; /* Round up to multiple of 8. */ bits = ntfs_malloc(bsize); if (!bits) return -ENOMEM; io.param = bits; io.size = bsize; error = ntfs_read_attr(bitmap, bitmap->vol->at_data, 0, loc >> 3, &io); - if (error || io.size != bsize){ + if (error || io.size != bsize) { ntfs_free(bits); return error ? error : -EIO; } /* Now set the bits. */ it = bits; locit = loc; - while (locit % 8 && cnt) { /* process first byte */ + while (locit % 8 && cnt) { /* Process first byte. */ if (bit) *it |= 1 << (locit % 8); else @@ -565,13 +627,13 @@ if (locit % 8 == 0) it++; } - while (cnt > 8) { /*process full bytes */ + while (cnt > 8) { /* Process full bytes. */ *it = bit ? 0xFF : 0; cnt -= 8; locit += 8; it++; } - while (cnt) { /*process last byte */ + while (cnt) { /* Process last byte. */ if (bit) *it |= 1 << (locit % 8); else @@ -579,7 +641,7 @@ cnt--; locit++; } - /* reset to start */ + /* Reset to start. */ io.param = bits; io.size = bsize; error = ntfs_write_attr(bitmap, bitmap->vol->at_data, 0, loc >> 3, &io); diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/super.h linux/fs/ntfs/super.h --- v2.4.9/linux/fs/ntfs/super.h Wed Jul 25 17:10:24 2001 +++ linux/fs/ntfs/super.h Tue Aug 28 06:57:18 2001 @@ -3,6 +3,7 @@ * * Copyright (C) 1995-1997 Martin von Löwis * Copyright (C) 1996-1997 Régis Duchesne + * Copyright (c) 2001 Anton Altaparmakov */ #define ALLOC_REQUIRE_LOCATION 1 @@ -18,13 +19,13 @@ int ntfs_release_volume(ntfs_volume *vol); -void ntfs_insert_fixups(unsigned char *rec, int secsize); +int ntfs_insert_fixups(unsigned char *rec, int rec_size); -int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size); +int ntfs_fixup_record(char *record, char *magic, int size); int ntfs_allocate_clusters(ntfs_volume *vol, ntfs_cluster_t *location, - int *count, int flags); + int *count, int flags); int ntfs_deallocate_clusters(ntfs_volume *vol, ntfs_cluster_t location, - int count); + int count); diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/support.c linux/fs/ntfs/support.c --- v2.4.9/linux/fs/ntfs/support.c Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/support.c Tue Aug 28 06:57:18 2001 @@ -17,10 +17,7 @@ #include "util.h" #include "inode.h" #include "macros.h" - -#ifndef NLS_MAX_CHARSET_SIZE #include -#endif static char print_buf[1024]; @@ -108,8 +105,8 @@ va_list ap; va_start(ap, fmt); - strcpy(print_buf, KERN_ERR); - vsprintf(print_buf + 3, fmt, ap); + strcpy(print_buf, KERN_ERR "NTFS: "); + vsprintf(print_buf + 9, fmt, ap); printk(print_buf); va_end(ap); } @@ -162,8 +159,8 @@ return 0; } -int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs, - ntfs_io *buf) +int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs, + ntfs_io *buf) { struct super_block *sb = NTFS_SB(vol); struct buffer_head *bh; @@ -173,6 +170,7 @@ ntfs_debug(DEBUG_OTHER, "%s_clusters %d %d %d\n", buf->do_read ? "get" : "put", cluster, start_offs, length); + to_copy = vol->cluster_size - start_offs; while (length) { if (!(bh = bread(sb->s_dev, cluster, vol->cluster_size))) { ntfs_debug(DEBUG_OTHER, "%s failed\n", @@ -180,7 +178,8 @@ error = -EIO; goto error_ret; } - to_copy = min(unsigned int, vol->cluster_size - start_offs, length); + if (to_copy > length) + to_copy = length; lock_buffer(bh); if (buf->do_read) { buf->fn_put(buf, bh->b_data + start_offs, to_copy); @@ -211,10 +210,11 @@ } } } + brelse(bh); length -= to_copy; start_offs = 0; + to_copy = vol->cluster_size; cluster++; - brelse(bh); } error_ret: return error; diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/unistr.c linux/fs/ntfs/unistr.c --- v2.4.9/linux/fs/ntfs/unistr.c Mon Aug 27 12:41:46 2001 +++ linux/fs/ntfs/unistr.c Tue Aug 28 06:57:18 2001 @@ -1,6 +1,4 @@ /* - * $Id: unistr.c,v 1.4 2001/04/08 03:02:55 antona Exp $ - * * unistr.c - Unicode string handling. Part of the Linux-NTFS project. * * Copyright (c) 2000,2001 Anton Altaparmakov. @@ -93,11 +91,13 @@ wchar_t *name2, __u32 name2_len, int ic, int err_val) { - __u32 cnt; + __u32 cnt, min_len; wchar_t c1, c2; - for (cnt = 0; cnt < min(unsigned int, name1_len, name2_len); ++cnt) - { + min_len = name1_len; + if (min_len > name2_len) + min_len = name2_len; + for (cnt = 0; cnt < min_len; ++cnt) { c1 = le16_to_cpu(*name1++); c2 = le16_to_cpu(*name2++); if (ic) { @@ -106,7 +106,7 @@ if (c2 < upcase_len) c2 = le16_to_cpu(upcase[c2]); } - if (c1 < 64 && legal_ansi_char_array[c1] & 8); + if (c1 < 64 && legal_ansi_char_array[c1] & 8) return err_val; if (c1 < c2) return -1; diff -u --recursive --new-file v2.4.9/linux/fs/ntfs/unistr.h linux/fs/ntfs/unistr.h --- v2.4.9/linux/fs/ntfs/unistr.h Wed Jul 25 17:10:24 2001 +++ linux/fs/ntfs/unistr.h Tue Aug 28 06:57:18 2001 @@ -1,6 +1,4 @@ /* - * $Id: unistr.h,v 1.5 2001/04/11 11:49:16 antona Exp $ - * * unistr.h - Exports for unicode string handling. Part of the Linux-NTFS * project. * diff -u --recursive --new-file v2.4.9/linux/fs/partitions/ibm.c linux/fs/partitions/ibm.c --- v2.4.9/linux/fs/partitions/ibm.c Sun Aug 12 13:28:00 2001 +++ linux/fs/partitions/ibm.c Mon Aug 27 14:20:21 2001 @@ -45,67 +45,22 @@ static int get_drive_geometry(int kdev,struct hd_geometry *geo) { - int rc = 0; - mm_segment_t old_fs; - struct file *filp; - struct inode *inode; - /* find out offset of volume label (partn table) */ - filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL); - if ( filp == NULL ) { - printk (KERN_WARNING __FILE__ " ibm_partition: kmalloc failed fo -r filp\n"); - return -ENOMEM; - } - memset(filp,0,sizeof(struct file)); - filp ->f_mode = 1; /* read only */ - inode = get_empty_inode(); - if ( inode == NULL ) - return -ENOMEM; - inode -> i_rdev = kdev; - inode -> i_bdev = bdget(kdev_t_to_nr(kdev)); - rc = blkdev_open(inode,filp); - if ( rc == 0 ) { - old_fs=get_fs(); - set_fs(KERNEL_DS); - rc = inode-> i_bdev -> bd_op->ioctl (inode, filp, HDIO_GETGEO, - (unsigned long)(geo)) - ; - set_fs(old_fs); - } - blkdev_put(inode->i_bdev,BDEV_FILE); + struct block_device *bdev = bdget(kdev_t_to_nr(kdev)); + int rc = blkdev_get(bdev, 0, 1, BDEV_FILE); + if ( rc == 0 ) + rc = ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo); + blkdev_put(bdev,BDEV_FILE); return rc; } static int get_drive_info(int kdev,dasd_information_t *info) { - int rc = 0; - mm_segment_t old_fs; - struct file *filp; - struct inode *inode; - /* find out offset of volume label (partn table) */ - filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL); - if ( filp == NULL ) { - printk (KERN_WARNING __FILE__ " ibm_partition: kmalloc failed fo -r filp\n"); - return -ENOMEM; - } - memset(filp,0,sizeof(struct file)); - filp ->f_mode = 1; /* read only */ - inode = get_empty_inode(); - if ( inode == NULL ) - return -ENOMEM; - inode -> i_rdev = kdev; - inode -> i_bdev = bdget(kdev_t_to_nr(kdev)); - rc = blkdev_open(inode,filp); - if ( rc == 0 ) { - old_fs=get_fs(); - set_fs(KERNEL_DS); - rc = inode-> i_bdev -> bd_op->ioctl (inode, filp, BIODASDINFO, - (unsigned long)(info)); - set_fs(old_fs); - } - blkdev_put(inode->i_bdev,BDEV_FILE); + struct block_device *bdev = bdget(kdev_t_to_nr(kdev)); + int rc = blkdev_get(bdev, 0, 1, BDEV_FILE); + if ( rc == 0 ) + rc = ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info)); + blkdev_put(bdev,BDEV_FILE); return rc; } diff -u --recursive --new-file v2.4.9/linux/fs/pipe.c linux/fs/pipe.c --- v2.4.9/linux/fs/pipe.c Fri Feb 9 11:29:44 2001 +++ linux/fs/pipe.c Tue Aug 28 10:56:06 2001 @@ -630,8 +630,7 @@ return sb; } -static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, - FS_NOMOUNT|FS_SINGLE); +static DECLARE_FSTYPE(pipe_fs_type, "pipefs", pipefs_read_super, FS_NOMOUNT); static int __init init_pipe_fs(void) { @@ -650,7 +649,7 @@ static void __exit exit_pipe_fs(void) { unregister_filesystem(&pipe_fs_type); - kern_umount(pipe_mnt); + mntput(pipe_mnt); } module_init(init_pipe_fs) diff -u --recursive --new-file v2.4.9/linux/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c --- v2.4.9/linux/fs/proc/proc_misc.c Wed Jul 25 17:10:24 2001 +++ linux/fs/proc/proc_misc.c Tue Aug 28 07:11:33 2001 @@ -573,7 +573,7 @@ entry->size = (1+prof_len) * sizeof(unsigned int); } } -#ifdef __powerpc__ +#ifdef CONFIG_PPC32 { extern struct file_operations ppc_htab_operations; entry = create_proc_entry("ppc_htab", S_IRUGO|S_IWUSR, NULL); diff -u --recursive --new-file v2.4.9/linux/fs/super.c linux/fs/super.c --- v2.4.9/linux/fs/super.c Sun Aug 12 13:28:00 2001 +++ linux/fs/super.c Tue Aug 28 10:56:06 2001 @@ -122,6 +122,7 @@ return -EINVAL; if (fs->next) return -EBUSY; + INIT_LIST_HEAD(&fs->fs_supers); write_lock(&file_systems_lock); p = find_filesystem(fs->name); if (*p) @@ -387,8 +388,6 @@ spin_lock(&dcache_lock); list_add(&mnt->mnt_list, vfsmntlist.prev); spin_unlock(&dcache_lock); - if (sb->s_type->fs_flags & FS_SINGLE) - get_filesystem(sb->s_type); out: return mnt; } @@ -435,8 +434,6 @@ list_add(&mnt->mnt_list, vfsmntlist.prev); spin_unlock(&dcache_lock); up(&nd->dentry->d_inode->i_zombie); - if (mnt->mnt_sb->s_type->fs_flags & FS_SINGLE) - get_filesystem(mnt->mnt_sb->s_type); mntget(mnt); return 0; fail: @@ -669,6 +666,7 @@ static void put_super(struct super_block *sb) { + atomic_dec(&sb->s_active); up_write(&sb->s_umount); __put_super(sb); } @@ -735,10 +733,6 @@ s = find_super(dev); if (s) { spin_unlock(&sb_lock); - /* Yes, it sucks. As soon as we get refcounting... */ - /* Almost there - next two lines will go away RSN */ - lock_super(s); - unlock_super(s); down_read(&s->s_umount); if (s->s_root) return s; @@ -792,6 +786,7 @@ INIT_LIST_HEAD(&s->s_dirty); INIT_LIST_HEAD(&s->s_locked_inodes); INIT_LIST_HEAD(&s->s_files); + INIT_LIST_HEAD(&s->s_instances); init_rwsem(&s->s_umount); sema_init(&s->s_lock, 1); s->s_count = 1; @@ -819,7 +814,10 @@ s->s_type = type; spin_lock(&sb_lock); list_add (&s->s_list, super_blocks.prev); + list_add (&s->s_instances, &type->fs_supers); + s->s_count += S_BIAS; spin_unlock(&sb_lock); + down_write(&s->s_umount); lock_super(s); if (!type->read_super(s, data, silent)) goto out_fail; @@ -835,11 +833,12 @@ s->s_bdev = 0; s->s_type = NULL; unlock_super(s); - atomic_dec(&s->s_active); spin_lock(&sb_lock); list_del(&s->s_list); + list_del(&s->s_instances); + s->s_count -= S_BIAS; spin_unlock(&sb_lock); - __put_super(s); + put_super(s); return NULL; } @@ -871,16 +870,38 @@ kdevname(dev)); } +static int grab_super(struct super_block *sb) +{ + sb->s_count++; + atomic_inc(&sb->s_active); + spin_unlock(&sb_lock); + down_write(&sb->s_umount); + if (sb->s_root) { + spin_lock(&sb_lock); + if (sb->s_count > S_BIAS) { + sb->s_count--; + spin_unlock(&sb_lock); + return 1; + } + spin_unlock(&sb_lock); + } + put_super(sb); + return 0; +} + static struct super_block *get_sb_bdev(struct file_system_type *fs_type, char *dev_name, int flags, void * data) { struct inode *inode; struct block_device *bdev; struct block_device_operations *bdops; - struct super_block * sb; + struct super_block * s; struct nameidata nd; + struct list_head *p; kdev_t dev; int error = 0; + mode_t mode = FMODE_READ; /* we always need it ;-) */ + /* What device it is? */ if (!dev_name || !*dev_name) return ERR_PTR(-EINVAL); @@ -901,50 +922,77 @@ /* Done with lookups, semaphore down */ down(&mount_sem); dev = to_kdev_t(bdev->bd_dev); - sb = get_super(dev); - if (sb) { - if (fs_type == sb->s_type && - ((flags ^ sb->s_flags) & MS_RDONLY) == 0) { -/* - * We are heavily relying on mount_sem here. We _will_ get rid of that - * ugliness RSN (and then atomicity of ->s_active will play), but first - * we need to get rid of "reuse" branch of get_empty_super() and that - * requires reference counters. Chicken and egg problem, but fortunately - * we can use the fact that right now all accesses to ->s_active are - * under mount_sem. - */ - if (atomic_read(&sb->s_active)) { - spin_lock(&sb_lock); - sb->s_count--; - spin_unlock(&sb_lock); - } - atomic_inc(&sb->s_active); - up_read(&sb->s_umount); - path_release(&nd); - return sb; - } - drop_super(sb); - } else { - mode_t mode = FMODE_READ; /* we always need it ;-) */ - if (!(flags & MS_RDONLY)) - mode |= FMODE_WRITE; - error = blkdev_get(bdev, mode, 0, BDEV_FS); - if (error) - goto out; - check_disk_change(dev); - error = -EACCES; - if (!(flags & MS_RDONLY) && is_read_only(dev)) + if (!(flags & MS_RDONLY)) + mode |= FMODE_WRITE; + error = blkdev_get(bdev, mode, 0, BDEV_FS); + if (error) + goto out; + check_disk_change(dev); + error = -EACCES; + if (!(flags & MS_RDONLY) && is_read_only(dev)) + goto out1; + + error = -ENOMEM; + s = alloc_super(); + if (!s) + goto out1; + down_write(&s->s_umount); + + error = -EBUSY; +restart: + spin_lock(&sb_lock); + + list_for_each(p, &super_blocks) { + struct super_block *old = sb_entry(p); + if (old->s_dev != dev) + continue; + if (old->s_type != fs_type || + ((flags ^ old->s_flags) & MS_RDONLY)) { + spin_unlock(&sb_lock); + put_super(s); goto out1; - error = -EINVAL; - sb = read_super(dev, bdev, fs_type, flags, data, 0); - if (sb) { - get_filesystem(fs_type); - path_release(&nd); - return sb; } -out1: + if (!grab_super(old)) + goto restart; + put_super(s); blkdev_put(bdev, BDEV_FS); + path_release(&nd); + return old; } + s->s_dev = dev; + s->s_bdev = bdev; + s->s_flags = flags; + s->s_type = fs_type; + list_add (&s->s_list, super_blocks.prev); + list_add (&s->s_instances, &fs_type->fs_supers); + s->s_count += S_BIAS; + + spin_unlock(&sb_lock); + + error = -EINVAL; + lock_super(s); + if (!fs_type->read_super(s, data, 0)) + goto out_fail; + unlock_super(s); + /* tell bdcache that we are going to keep this one */ + atomic_inc(&bdev->bd_count); + get_filesystem(fs_type); + path_release(&nd); + return s; + +out_fail: + s->s_dev = 0; + s->s_bdev = 0; + s->s_type = NULL; + unlock_super(s); + spin_lock(&sb_lock); + list_del(&s->s_list); + list_del(&s->s_instances); + s->s_count -= S_BIAS; + spin_unlock(&sb_lock); + put_super(s); +out1: + blkdev_put(bdev, BDEV_FS); out: path_release(&nd); up(&mount_sem); @@ -975,18 +1023,62 @@ static struct super_block *get_sb_single(struct file_system_type *fs_type, int flags, void *data) { - struct super_block * sb; + struct super_block * s = alloc_super(); + if (!s) + return ERR_PTR(-ENOMEM); + down_write(&s->s_umount); /* * Get the superblock of kernel-wide instance, but * keep the reference to fs_type. */ down(&mount_sem); - sb = fs_type->kern_mnt->mnt_sb; - if (!sb) - BUG(); - atomic_inc(&sb->s_active); - do_remount_sb(sb, flags, data); - return sb; +retry: + spin_lock(&sb_lock); + if (!list_empty(&fs_type->fs_supers)) { + struct super_block *old; + old = list_entry(fs_type->fs_supers.next, struct super_block, + s_instances); + if (!grab_super(old)) + goto retry; + put_super(s); + do_remount_sb(old, flags, data); + return old; + } else { + kdev_t dev = get_unnamed_dev(); + if (!dev) { + put_super(s); + up(&mount_sem); + return ERR_PTR(-EMFILE); + } + s->s_dev = dev; + s->s_flags = flags; + s->s_type = fs_type; + list_add (&s->s_list, super_blocks.prev); + list_add (&s->s_instances, &fs_type->fs_supers); + s->s_count += S_BIAS; + spin_unlock(&sb_lock); + lock_super(s); + if (!fs_type->read_super(s, data, 0)) + goto out_fail; + unlock_super(s); + get_filesystem(fs_type); + return s; + + out_fail: + s->s_dev = 0; + s->s_bdev = 0; + s->s_type = NULL; + unlock_super(s); + spin_lock(&sb_lock); + list_del(&s->s_list); + list_del(&s->s_instances); + s->s_count -= S_BIAS; + spin_unlock(&sb_lock); + put_super(s); + put_unnamed_dev(dev); + up(&mount_sem); + return ERR_PTR(-EINVAL); + } } static void kill_super(struct super_block *sb) @@ -997,8 +1089,12 @@ struct file_system_type *fs = sb->s_type; struct super_operations *sop = sb->s_op; - if (!atomic_dec_and_test(&sb->s_active)) + if (!atomic_dec_and_lock(&sb->s_active, &sb_lock)) return; + + sb->s_count -= S_BIAS; + spin_unlock(&sb_lock); + down_write(&sb->s_umount); lock_kernel(); sb->s_root = NULL; @@ -1037,7 +1133,9 @@ put_unnamed_dev(dev); spin_lock(&sb_lock); list_del(&sb->s_list); + list_del(&sb->s_instances); spin_unlock(&sb_lock); + atomic_inc(&sb->s_active); put_super(sb); } @@ -1056,7 +1154,7 @@ if (flags & MS_RDONLY) acct_auto_close(sb->s_dev); shrink_dcache_sb(sb); - fsync_dev(sb->s_dev); + fsync_super(sb); /* If we are remounting RDONLY, make sure there are no rw files open */ if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) if (!fs_may_remount_ro(sb)) @@ -1083,27 +1181,24 @@ { struct super_block *sb; struct vfsmount *mnt = alloc_vfsmnt(); - kdev_t dev; if (!mnt) return ERR_PTR(-ENOMEM); - dev = get_unnamed_dev(); - if (!dev) { - kmem_cache_free(mnt_cache, mnt); - return ERR_PTR(-EMFILE); - } - sb = read_super(dev, NULL, type, 0, NULL, 0); - if (!sb) { - put_unnamed_dev(dev); + if (type->fs_flags & FS_SINGLE) + sb = get_sb_single(type, 0, NULL); + else + sb = get_sb_nodev(type, 0, NULL); + if (IS_ERR(sb)) { kmem_cache_free(mnt_cache, mnt); - return ERR_PTR(-EINVAL); + return (struct vfsmount *)sb; } mnt->mnt_sb = sb; mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - type->kern_mnt = mnt; + up_write(&sb->s_umount); + up(&mount_sem); return mnt; } @@ -1140,8 +1235,11 @@ * Special case for "unmounting" root ... * we just try to remount it readonly. */ - if (!(sb->s_flags & MS_RDONLY)) + if (!(sb->s_flags & MS_RDONLY)) { + down_write(&sb->s_umount); retval = do_remount_sb(sb, MS_RDONLY, 0); + up_write(&sb->s_umount); + } return retval; } @@ -1152,8 +1250,6 @@ spin_unlock(&dcache_lock); return -EBUSY; } - if (sb->s_type->fs_flags & FS_SINGLE) - put_filesystem(sb->s_type); detach_mnt(mnt, &parent_nd); list_del(&mnt->mnt_list); spin_unlock(&dcache_lock); @@ -1317,13 +1413,19 @@ static int do_remount(struct nameidata *nd, int flags, char *data) { + int err; + struct super_block * sb = nd->mnt->mnt_sb; + if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (nd->dentry != nd->mnt->mnt_root) return -EINVAL; - return do_remount_sb(nd->mnt->mnt_sb, flags, data); + down_write(&sb->s_umount); + err = do_remount_sb(sb, flags, data); + up_write(&sb->s_umount); + return err; } static int do_add_mount(struct nameidata *nd, char *type, int flags, @@ -1379,6 +1481,7 @@ mnt->mnt_root = dget(sb->s_root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; + up_write(&sb->s_umount); /* Something was mounted here while we slept */ while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) @@ -1639,6 +1742,7 @@ fs_type = sb->s_type; atomic_inc(&sb->s_active); up_read(&sb->s_umount); + down_write(&sb->s_umount); goto mount_it; } @@ -1659,6 +1763,8 @@ panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV)); mount_it: + /* FIXME */ + up_write(&sb->s_umount); printk ("VFS: Mounted root (%s filesystem)%s.\n", fs_type->name, (sb->s_flags & MS_RDONLY) ? " readonly" : ""); diff -u --recursive --new-file v2.4.9/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c --- v2.4.9/linux/fs/umsdos/dir.c Fri Feb 9 11:29:44 2001 +++ linux/fs/umsdos/dir.c Tue Aug 28 08:16:07 2001 @@ -67,7 +67,7 @@ static int umsdos_dir_once ( void *buf, const char *name, int len, - off_t offset, + loff_t offset, ino_t ino, unsigned type) { diff -u --recursive --new-file v2.4.9/linux/fs/umsdos/emd.c linux/fs/umsdos/emd.c --- v2.4.9/linux/fs/umsdos/emd.c Tue Mar 6 19:44:37 2001 +++ linux/fs/umsdos/emd.c Mon Aug 27 08:13:05 2001 @@ -259,10 +259,10 @@ p->ctime = cpu_to_le32(entry->ctime); p->rdev = cpu_to_le16(entry->rdev); p->mode = cpu_to_le16(entry->mode); - memcpy(p->name,entry->name, + memcpy(p->spare,entry->spare, (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare); memcpy(page_address(page2), - entry->spare+PAGE_CACHE_SIZE-offs, + ((char*)entry)+PAGE_CACHE_SIZE-offs, offs+info->recsize-PAGE_CACHE_SIZE); ret = mapping->a_ops->commit_write(NULL,page2,0, offs+info->recsize-PAGE_CACHE_SIZE); diff -u --recursive --new-file v2.4.9/linux/fs/umsdos/ioctl.c linux/fs/umsdos/ioctl.c --- v2.4.9/linux/fs/umsdos/ioctl.c Wed Apr 18 11:49:13 2001 +++ linux/fs/umsdos/ioctl.c Tue Aug 28 08:16:07 2001 @@ -28,7 +28,7 @@ void *buf, const char *name, int name_len, - off_t offset, + loff_t offset, ino_t ino, unsigned type) { diff -u --recursive --new-file v2.4.9/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c --- v2.4.9/linux/fs/umsdos/rdir.c Fri Feb 9 11:29:44 2001 +++ linux/fs/umsdos/rdir.c Tue Aug 28 08:16:07 2001 @@ -32,7 +32,7 @@ static int rdir_filldir ( void *buf, const char *name, int name_len, - off_t offset, + loff_t offset, ino_t ino, unsigned int d_type) { diff -u --recursive --new-file v2.4.9/linux/include/asm-alpha/keyboard.h linux/include/asm-alpha/keyboard.h --- v2.4.9/linux/include/asm-alpha/keyboard.h Mon Aug 27 12:41:47 2001 +++ linux/include/asm-alpha/keyboard.h Tue Aug 28 07:09:44 2001 @@ -22,7 +22,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]; @@ -31,7 +30,6 @@ #define kbd_translate pckbd_translate #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds -#define kbd_rate pckbd_rate #define kbd_init_hw pckbd_init_hw #define kbd_sysrq_xlate pckbd_sysrq_xlate diff -u --recursive --new-file v2.4.9/linux/include/asm-i386/keyboard.h linux/include/asm-i386/keyboard.h --- v2.4.9/linux/include/asm-i386/keyboard.h Mon Aug 27 12:41:48 2001 +++ linux/include/asm-i386/keyboard.h Tue Aug 28 07:09:44 2001 @@ -27,7 +27,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 void pckbd_pm_resume(void); extern unsigned char pckbd_sysrq_xlate[128]; @@ -37,7 +36,6 @@ #define kbd_translate pckbd_translate #define kbd_unexpected_up pckbd_unexpected_up #define kbd_leds pckbd_leds -#define kbd_rate pckbd_rate #define kbd_init_hw pckbd_init_hw #define kbd_sysrq_xlate pckbd_sysrq_xlate diff -u --recursive --new-file v2.4.9/linux/include/asm-i386/kmap_types.h linux/include/asm-i386/kmap_types.h --- v2.4.9/linux/include/asm-i386/kmap_types.h Thu Apr 12 12:11:39 2001 +++ linux/include/asm-i386/kmap_types.h Mon Aug 27 07:43:02 2001 @@ -6,6 +6,8 @@ KM_BOUNCE_WRITE, KM_SKB_DATA, KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, KM_TYPE_NR }; diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/atomic.h linux/include/asm-ppc/atomic.h --- v2.4.9/linux/include/asm-ppc/atomic.h Wed Jul 25 17:10:25 2001 +++ linux/include/asm-ppc/atomic.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.atomic.h 1.8 05/17/01 18:14:24 cort + * BK Id: SCCS/s.atomic.h 1.13 08/21/01 16:07:48 trini */ /* * PowerPC atomic operations @@ -7,6 +7,7 @@ #ifndef _ASM_PPC_ATOMIC_H_ #define _ASM_PPC_ATOMIC_H_ +#ifdef __KERNEL__ typedef struct { volatile int counter; } atomic_t; @@ -18,75 +19,137 @@ extern void atomic_clear_mask(unsigned long mask, unsigned long *addr); extern void atomic_set_mask(unsigned long mask, unsigned long *addr); -static __inline__ int atomic_add_return(int a, atomic_t *v) +#ifdef CONFIG_SMP +#define SMP_ISYNC "\n\tisync" +#else +#define SMP_ISYNC +#endif + +static __inline__ void atomic_add(int a, atomic_t *v) { int t; - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3\n\ + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_add\n\ add %0,%2,%0\n\ stwcx. %0,0,%3\n\ bne- 1b" : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (v), "m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) : "cc"); +} + +static __inline__ int atomic_add_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_add_return\n\ + add %0,%1,%0\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); return t; } -static __inline__ int atomic_sub_return(int a, atomic_t *v) +static __inline__ void atomic_sub(int a, atomic_t *v) { int t; - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3\n\ + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_sub\n\ subf %0,%2,%0\n\ stwcx. %0,0,%3\n\ bne- 1b" : "=&r" (t), "=m" (v->counter) - : "r" (a), "r" (v), "m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) : "cc"); +} + +static __inline__ int atomic_sub_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_sub_return\n\ + subf %0,%1,%0\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); return t; } -static __inline__ int atomic_inc_return(atomic_t *v) +static __inline__ void atomic_inc(atomic_t *v) { int t; - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2\n\ + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_inc\n\ addic %0,%0,1\n\ stwcx. %0,0,%2\n\ bne- 1b" : "=&r" (t), "=m" (v->counter) - : "r" (v), "m" (v->counter) + : "r" (&v->counter), "m" (v->counter) : "cc"); +} + +static __inline__ int atomic_inc_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%1 # atomic_inc_return\n\ + addic %0,%0,1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); return t; } -static __inline__ int atomic_dec_return(atomic_t *v) +static __inline__ void atomic_dec(atomic_t *v) { int t; - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2\n\ + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_dec\n\ addic %0,%0,-1\n\ stwcx. %0,0,%2\n\ - bne 1b" + bne- 1b" : "=&r" (t), "=m" (v->counter) - : "r" (v), "m" (v->counter) + : "r" (&v->counter), "m" (v->counter) : "cc"); +} + +static __inline__ int atomic_dec_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%1 # atomic_dec_return\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); return t; } -#define atomic_add(a, v) ((void) atomic_add_return((a), (v))) -#define atomic_sub(a, v) ((void) atomic_sub_return((a), (v))) #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) -#define atomic_inc(v) ((void) atomic_inc_return((v))) -#define atomic_dec(v) ((void) atomic_dec_return((v))) #define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) /* @@ -97,16 +160,17 @@ { int t; - __asm__ __volatile__("\n" -"1: lwarx %0,0,%2\n" -" addic. %0,%0,-1\n" -" blt 2f\n" -" stwcx. %0,0,%2\n" -" bne 1b\n" -"2:" - : "=&r" (t), "=m" (v->counter) - : "r" (&v->counter), "m" (v->counter) - : "cc"); + __asm__ __volatile__( +"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ + addic. %0,%0,-1\n\ + blt- 2f\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + SMP_ISYNC + "\n\ +2:" : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); return t; } @@ -116,4 +180,5 @@ #define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb() +#endif /* __KERNEL__ */ #endif /* _ASM_PPC_ATOMIC_H_ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/bootinfo.h linux/include/asm-ppc/bootinfo.h --- v2.4.9/linux/include/asm-ppc/bootinfo.h Tue Jul 3 17:08:21 2001 +++ linux/include/asm-ppc/bootinfo.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.bootinfo.h 1.9 06/13/01 15:28:43 paulus + * BK Id: SCCS/s.bootinfo.h 1.11 08/17/01 15:23:17 paulus */ /* * Non-machine dependent bootinfo structure. Basic idea @@ -31,6 +31,7 @@ #define BI_INITRD 0x1014 #define BI_SYSMAP 0x1015 #define BI_MACHTYPE 0x1016 +#define BI_MEMSIZE 0x1017 #endif /* CONFIG_APUS */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/bseip.h linux/include/asm-ppc/bseip.h --- v2.4.9/linux/include/asm-ppc/bseip.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/bseip.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.bseip.h 1.7 05/17/01 18:14:24 cort + * BK Id: SCCS/s.bseip.h 1.10 08/17/01 15:23:17 paulus */ /* @@ -38,9 +38,5 @@ /* We don't use the 8259. */ #define NR_8259_INTS 0 - -/* Machine type -*/ -#define _MACH_8xx (_MACH_bseip) #endif diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/btext.h linux/include/asm-ppc/btext.h --- v2.4.9/linux/include/asm-ppc/btext.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/btext.h Tue Aug 28 06:58:33 2001 @@ -0,0 +1,37 @@ +/* + * BK Id: %F% %I% %G% %U% %#% + */ +/* + * Definitions for using the procedures in btext.c. + * + * Benjamin Herrenschmidt + */ +#ifndef __PPC_BTEXT_H +#define __PPC_BTEXT_H +#ifdef __KERNEL__ + +#include + +extern void btext_clearscreen(void); +extern void btext_flushscreen(void); + +extern unsigned long disp_BAT[2]; + +extern boot_infos_t *disp_bi; +extern int boot_text_mapped; + +void btext_init(boot_infos_t *bi); +void btext_welcome(boot_infos_t* bi); +void btext_prepare_BAT(void); +void btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address); +void map_boot_text(void); +void btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch); + +void btext_drawchar(char c); +void btext_drawstring(const char *str); +void btext_drawhex(unsigned long v); + +#endif /* __KERNEL__ */ +#endif /* __PPC_BTEXT_H */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/cputable.h linux/include/asm-ppc/cputable.h --- v2.4.9/linux/include/asm-ppc/cputable.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-ppc/cputable.h Tue Aug 28 06:58:33 2001 @@ -0,0 +1,92 @@ +/* + * BK Id: SCCS/s.cputable.h 1.3 08/19/01 22:31:46 paulus + */ +/* + * include/asm-ppc/cputable.h + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __ASM_PPC_CPUTABLE_H +#define __ASM_PPC_CPUTABLE_H + +/* Exposed to userland CPU features */ +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +/* This structure can grow, it's real size is used by head.S code + * via the mkdefs mecanism. + */ +struct cpu_spec { + /* CPU is matched via (PVR & pvr_mask) == pvr_value */ + unsigned int pvr_mask; + unsigned int pvr_value; + + char *cpu_name; + unsigned int cpu_features; /* Kernel features */ + unsigned int cpu_user_features; /* Userland features */ + + /* cache line sizes */ + unsigned int icache_bsize; + unsigned int dcache_bsize; + + /* this is called to initialize various CPU bits like L1 cache, + * BHT, SPD, etc... from head.S before branching to identify_machine + */ + void (*cpu_setup)(int cpu_nr); +}; + +extern struct cpu_spec cpu_specs[]; +extern struct cpu_spec *cur_cpu_spec[]; + +#endif /* __ASSEMBLY__ */ + +/* CPU kernel features */ +#define CPU_FTR_SPLIT_ID_CACHE 0x00000001 +#define CPU_FTR_L2CR 0x00000002 +#define CPU_FTR_SPEC7450 0x00000004 +#define CPU_FTR_ALTIVEC 0x00000008 +#define CPU_FTR_TAU 0x00000010 +#define CPU_FTR_CAN_DOZE 0x00000020 +#define CPU_FTR_USE_TB 0x00000040 +#define CPU_FTR_604_PERF_MON 0x00000080 +#define CPU_FTR_601 0x00000100 +#define CPU_FTR_HPTE_TABLE 0x00000200 + +#ifdef __ASSEMBLY__ + +#define BEGIN_FTR_SECTION 98: + +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 2; \ + .long msk; \ + .long val; \ + .long 98b; \ + .long 99b; \ + .previous + +#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) +#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_PPC_CPUTABLE_H */ +#endif /* __KERNEL__ */ + diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h --- v2.4.9/linux/include/asm-ppc/elf.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/elf.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.elf.h 1.10 05/17/01 18:14:24 cort + * BK Id: SCCS/s.elf.h 1.14 08/21/01 16:07:48 trini */ #ifndef __PPC_ELF_H #define __PPC_ELF_H @@ -7,7 +7,9 @@ /* * ELF register definitions.. */ +#include #include +#include #define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ #define ELF_NFPREG 33 /* includes fpscr */ @@ -60,7 +62,7 @@ instruction set this cpu supports. This could be done in userspace, but it's not easy, and we've already done it here. */ -#define ELF_HWCAP (0) +#define ELF_HWCAP (cur_cpu_spec[0]->cpu_user_features) /* This yields a string that ld.so will use to load implementation specific libraries for optimization. This is more specific in diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/fads.h linux/include/asm-ppc/fads.h --- v2.4.9/linux/include/asm-ppc/fads.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/fads.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.fads.h 1.8 05/17/01 18:14:24 cort + * BK Id: SCCS/s.fads.h 1.11 08/17/01 15:23:17 paulus */ /* @@ -66,8 +66,4 @@ */ #define NR_8259_INTS 0 -/* Machine type - */ -#define _MACH_8xx (_MACH_fads) - #endif diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/feature.h linux/include/asm-ppc/feature.h --- v2.4.9/linux/include/asm-ppc/feature.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/feature.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.feature.h 1.9 05/17/01 18:14:24 cort + * BK Id: SCCS/s.feature.h 1.13 08/19/01 22:23:04 paulus */ /* * Definitions for accessing the Feature Control Register (FCR) @@ -91,6 +91,8 @@ extern void feature_set_firewire_power(struct device_node* device, int power); extern void feature_set_firewire_cable_power(struct device_node* device, int power); + +extern void feature_set_modem_power(struct device_node* device, int power); extern void feature_set_airport_power(struct device_node* device, int power); diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h --- v2.4.9/linux/include/asm-ppc/ide.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/ide.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ide.h 1.10 05/17/01 18:14:24 cort + * BK Id: SCCS/s.ide.h 1.13 08/20/01 15:25:16 paulus */ /* * linux/include/asm-ppc/ide.h @@ -29,22 +29,9 @@ #include #include -extern int pmac_ide_ports_known; -extern ide_ioreg_t pmac_ide_regbase[MAX_HWIFS]; -extern int pmac_ide_irq[MAX_HWIFS]; -extern void pmac_ide_probe(void); - -extern int chrp_ide_ports_known; -extern ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; -extern ide_ioreg_t chrp_idedma_regbase; /* one for both channels */ -extern unsigned int chrp_ide_irq; -extern void chrp_ide_probe(void); - extern void ppc_generic_ide_fix_driveid(struct hd_driveid *id); struct ide_machdep_calls { - void (*insw)(ide_ioreg_t port, void *buf, int ns); - void (*outsw)(ide_ioreg_t port, void *buf, int ns); int (*default_irq)(ide_ioreg_t base); ide_ioreg_t (*default_io_base)(int index); int (*ide_check_region)(ide_ioreg_t from, unsigned int extent); @@ -53,30 +40,16 @@ const char *name); void (*ide_release_region)(ide_ioreg_t from, unsigned int extent); - void (*fix_driveid)(struct hd_driveid *id); void (*ide_init_hwif)(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq); - - int io_base; }; extern struct ide_machdep_calls ppc_ide_md; -void ide_insw(ide_ioreg_t port, void *buf, int ns); -void ide_outsw(ide_ioreg_t port, void *buf, int ns); void ppc_generic_ide_fix_driveid(struct hd_driveid *id); - -#undef insw -#define insw(port, buf, ns) do { \ - ppc_ide_md.insw((port), (buf), (ns)); \ -} while (0) - -#undef outsw -#define outsw(port, buf, ns) do { \ - ppc_ide_md.outsw((port), (buf), (ns)); \ -} while (0) +#define ide_fix_driveid(id) ppc_generic_ide_fix_driveid((id)) #undef SUPPORT_SLOW_DATA_PORTS #define SUPPORT_SLOW_DATA_PORTS 0 @@ -87,10 +60,9 @@ static __inline__ int ide_default_irq(ide_ioreg_t base) { - if ( ppc_ide_md.default_irq ) + if (ppc_ide_md.default_irq) return ppc_ide_md.default_irq(base); - else - return -1; + return 0; } static __inline__ ide_ioreg_t ide_default_io_base(int index) @@ -100,7 +72,7 @@ return 0; } -static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, +static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { @@ -135,20 +107,14 @@ static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name) { - if ( ppc_ide_md.ide_request_region ) + if (ppc_ide_md.ide_request_region) ppc_ide_md.ide_request_region(from, extent, name); } static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent) { - if ( ppc_ide_md.ide_release_region ) + if (ppc_ide_md.ide_release_region) ppc_ide_md.ide_release_region(from, extent); -} - -static __inline__ void ide_fix_driveid (struct hd_driveid *id) -{ - if ( ppc_ide_md.fix_driveid ) - ppc_ide_md.fix_driveid(id); } typedef union { diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h --- v2.4.9/linux/include/asm-ppc/io.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/io.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.io.h 1.7 05/17/01 18:14:24 cort + * BK Id: SCCS/s.io.h 1.11 08/28/01 15:48:26 paulus */ #ifdef __KERNEL__ #ifndef _PPC_IO_H @@ -24,7 +24,7 @@ #define PREP_PCI_DRAM_OFFSET 0x80000000 #if defined(CONFIG_4xx) -#include +#include #elif defined(CONFIG_8xx) #include #elif defined(CONFIG_8260) @@ -185,15 +185,13 @@ */ extern void *__ioremap(unsigned long address, unsigned long size, unsigned long flags); -extern void *__ioremap_at(unsigned long phys, unsigned long size, - unsigned long flags); extern void *ioremap(unsigned long address, unsigned long size); #define ioremap_nocache(addr, size) ioremap((addr), (size)) extern void iounmap(void *addr); extern unsigned long iopa(unsigned long addr); -#ifdef CONFIG_APUS extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); -#endif +extern void io_block_mapping(unsigned long virt, unsigned long phys, + unsigned int size, int flags); /* * The PCI bus is inherently Little-Endian. The PowerPC is being @@ -245,6 +243,12 @@ return (void*) mm_ptov (address); #endif } + +/* + * Change "struct page" to physical address. + */ +#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) +#define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET) #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/ivms8.h linux/include/asm-ppc/ivms8.h --- v2.4.9/linux/include/asm-ppc/ivms8.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/ivms8.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.ivms8.h 1.5 05/17/01 18:14:24 cort + * BK Id: SCCS/s.ivms8.h 1.6 08/17/01 15:23:17 paulus */ /* * A collection of structures, addresses, and values associated with @@ -87,9 +87,4 @@ */ #define NR_8259_INTS 0 -/* Generic 8xx type -*/ -#define _MACH_8xx (_MACH_ivms8) - #endif /* __MACH_IVMS8_DEFS */ - diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/keyboard.h linux/include/asm-ppc/keyboard.h --- v2.4.9/linux/include/asm-ppc/keyboard.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/keyboard.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.keyboard.h 1.5 05/17/01 18:14:24 cort + * BK Id: %F% %I% %G% %U% %#% */ /* * linux/include/asm-ppc/keyboard.h @@ -23,6 +23,7 @@ #include #include +#include #include #define KEYBOARD_IRQ 1 @@ -67,13 +68,14 @@ if ( ppc_md.kbd_leds ) ppc_md.kbd_leds(leds); } - + static inline void kbd_init_hw(void) { if ( ppc_md.kbd_init_hw ) ppc_md.kbd_init_hw(); } +#define kbd_rate (ppc_md.kbd_rate_fn) #define kbd_sysrq_xlate (ppc_md.ppc_kbd_sysrq_xlate) extern unsigned long SYSRQ_KEY; diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/keylargo.h linux/include/asm-ppc/keylargo.h --- v2.4.9/linux/include/asm-ppc/keylargo.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/keylargo.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.keylargo.h 1.9 05/17/01 18:14:24 cort + * BK Id: SCCS/s.keylargo.h 1.13 08/19/01 22:23:04 paulus */ /* * keylargo.h: definitions for using the "KeyLargo" I/O controller chip. @@ -35,7 +35,12 @@ #define KL_GPIO_MODEM_RESET (KEYLARGO_GPIO_0+0x03) /* Pangea */ #define KL_GPIO_MODEM_POWER (KEYLARGO_GPIO_0+0x02) /* Pangea */ +/* Hrm... this one is only to be used on Pismo. It seeem to also + * control the timebase enable on other machines. Still to be + * experimented... --BenH. + */ #define KL_GPIO_FW_CABLE_POWER (KEYLARGO_GPIO_0+0x09) +#define KL_GPIO_TB_ENABLE (KEYLARGO_GPIO_0+0x09) #define KL_GPIO_ETH_PHY_RESET (KEYLARGO_GPIO_0+0x10) diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h --- v2.4.9/linux/include/asm-ppc/machdep.h Tue Jul 3 17:08:21 2001 +++ linux/include/asm-ppc/machdep.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.machdep.h 1.14 06/28/01 16:13:50 paulus + * BK Id: SCCS/s.machdep.h 1.19 08/18/01 18:16:33 paulus */ #ifdef __KERNEL__ #ifndef _PPC_MACHDEP_H @@ -14,6 +14,7 @@ struct pt_regs; struct pci_bus; struct pci_dev; +struct kbd_repeat; struct machdep_calls { void (*setup_arch)(void); @@ -44,6 +45,8 @@ unsigned long heartbeat_count; unsigned long (*find_end_of_memory)(void); + void (*setup_io_mappings)(void); + void (*progress)(char *, unsigned short); unsigned char (*nvram_read_val)(int addr); @@ -58,6 +61,7 @@ char raw_mode); char (*kbd_unexpected_up)(unsigned char keycode); void (*kbd_leds)(unsigned char leds); + int (*kbd_rate_fn)(struct kbd_repeat *rep); void (*kbd_init_hw)(void); #ifdef CONFIG_MAGIC_SYSRQ unsigned char *ppc_kbd_sysrq_xlate; @@ -83,6 +87,11 @@ /* this is for modules, since _machine can be a define -- Cort */ int ppc_machine; + +#ifdef CONFIG_SMP + /* functions for dealing with other cpus */ + struct smp_ops_t *smp_ops; +#endif /* CONFIG_SMP */ }; extern struct machdep_calls ppc_md; @@ -101,6 +110,15 @@ } sys_ctrler_t; extern sys_ctrler_t sys_ctrler; + +#ifdef CONFIG_SMP +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); +}; +#endif /* CONFIG_SMP */ #endif /* _PPC_MACHDEP_H */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/mbx.h linux/include/asm-ppc/mbx.h --- v2.4.9/linux/include/asm-ppc/mbx.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/mbx.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.mbx.h 1.8 05/17/01 18:14:25 cort + * BK Id: SCCS/s.mbx.h 1.11 08/17/01 15:23:17 paulus */ /* * A collection of structures, addresses, and values associated with @@ -94,8 +94,5 @@ */ #define NR_8259_INTS 16 -/* Generic 8xx type -*/ -#define _MACH_8xx (_MACH_mbx) #endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h --- v2.4.9/linux/include/asm-ppc/mmu_context.h Tue Jul 3 17:08:21 2001 +++ linux/include/asm-ppc/mmu_context.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.mmu_context.h 1.12 06/28/01 15:50:17 paulus + * BK Id: SCCS/s.mmu_context.h 1.15 08/16/01 23:00:17 paulus */ #ifdef __KERNEL__ #ifndef __PPC_MMU_CONTEXT_H @@ -58,16 +58,19 @@ #ifdef CONFIG_8xx #define NO_CONTEXT 16 #define LAST_CONTEXT 15 +#define FIRST_CONTEXT 0 #elif CONFIG_4xx #define NO_CONTEXT 256 #define LAST_CONTEXT 255 +#define FIRST_CONTEXT 1 #else /* PPC 6xx, 7xx CPUs */ #define NO_CONTEXT ((mm_context_t) -1) #define LAST_CONTEXT 32767 +#define FIRST_CONTEXT 1 #endif /* @@ -75,11 +78,12 @@ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by * loading up the segment registers for the user part of the address space. * - * On the 8xx parts, the context currently includes the page directory, - * and once I implement a real TLB context manager this will disappear. - * The PGD is ignored on other processors. - Dan + * Since the PGD is immediately available, it is much faster to simply + * pass this along as a second parameter, which is required for 8xx and + * can be used for debugging on all processors (if you happen to have + * an Abatron). */ -extern void set_context(mm_context_t context); +extern void set_context(mm_context_t context, pgd_t *pgd); /* * Bitmap of contexts in use. @@ -156,7 +160,7 @@ { tsk->thread.pgdir = next->pgd; get_mmu_context(next); - set_context(next->context); + set_context(next->context, next->pgd); } /* @@ -167,8 +171,10 @@ { current->thread.pgdir = mm->pgd; get_mmu_context(mm); - set_context(mm->context); + set_context(mm->context, mm->pgd); } + +extern void mmu_context_init(void); #endif /* __PPC_MMU_CONTEXT_H */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h --- v2.4.9/linux/include/asm-ppc/page.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/page.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.page.h 1.5 05/17/01 18:14:25 cort + * BK Id: SCCS/s.page.h 1.8 08/19/01 20:06:47 paulus */ #ifndef _PPC_PAGE_H #define _PPC_PAGE_H @@ -12,6 +12,7 @@ #ifdef __KERNEL__ #include +/* Be sure to change arch/ppc/Makefile to match */ #define PAGE_OFFSET 0xc0000000 #define KERNELBASE PAGE_OFFSET diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/param.h linux/include/asm-ppc/param.h --- v2.4.9/linux/include/asm-ppc/param.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/param.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.param.h 1.5 05/17/01 18:14:25 cort + * BK Id: SCCS/s.param.h 1.8 08/20/01 22:50:29 paulus */ #ifndef _ASM_PPC_PARAM_H #define _ASM_PPC_PARAM_H @@ -21,7 +21,7 @@ #define MAXHOSTNAMELEN 64 /* max length of hostname */ #ifdef __KERNEL__ -# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */ +# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */ #endif #endif diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.4.9/linux/include/asm-ppc/processor.h Sun Aug 12 13:28:00 2001 +++ linux/include/asm-ppc/processor.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.processor.h 1.24 06/15/01 13:56:56 paulus + * BK Id: SCCS/s.processor.h 1.28 08/17/01 15:23:17 paulus */ #ifdef __KERNEL__ #ifndef __ASM_PPC_PROCESSOR_H @@ -475,33 +475,13 @@ #define PVR_8240 0x00810100 #define PVR_8260 PVR_8240 - -/* I am just adding a single entry for 8260 boards. I think we may be - * able to combine mbx, fads, rpxlite, bseip, and classic into a single - * generic 8xx as well. The boards containing these processors are either - * identical at the processor level (due to the high integration) or so - * wildly different that testing _machine at run time is best replaced by - * conditional compilation by board type (found in their respective .h file). - * -- Dan +/* We only need to define a new _MACH_xxx for machines which are part of + * a configuration which supports more than one type of different machine. + * This is currently limited to CONFIG_ALL_PPC and CHRP/PReP/PMac. -- Tom */ #define _MACH_prep 0x00000001 #define _MACH_Pmac 0x00000002 /* pmac or pmac clone (non-chrp) */ #define _MACH_chrp 0x00000004 /* chrp machine */ -#define _MACH_mbx 0x00000008 /* Motorola MBX board */ -#define _MACH_apus 0x00000010 /* amiga with phase5 powerup */ -#define _MACH_fads 0x00000020 /* Motorola FADS board */ -#define _MACH_rpxlite 0x00000040 /* RPCG RPX-Lite 8xx board */ -#define _MACH_bseip 0x00000080 /* Bright Star Engineering ip-Engine */ -#define _MACH_unused0 0x00000100 /* Now free to be used */ -#define _MACH_gemini 0x00000200 /* Synergy Microsystems gemini board */ -#define _MACH_classic 0x00000400 /* RPCG RPX-Classic 8xx board */ -#define _MACH_oak 0x00000800 /* IBM "Oak" 403 eval. board */ -#define _MACH_walnut 0x00001000 /* IBM "Walnut" 405GP eval. board */ -#define _MACH_8260 0x00002000 /* Generic 8260 */ -#define _MACH_tqm860 0x00004000 /* TQM860/L */ -#define _MACH_tqm8xxL 0x00008000 /* TQM8xxL */ -#define _MACH_spd8xx 0x00010000 /* SPD8xx */ -#define _MACH_ivms8 0x00020000 /* IVMS8 */ /* see residual.h for these */ #define _PREP_Motorola 0x01 /* motorola prep */ @@ -558,11 +538,10 @@ #ifndef __ASSEMBLY__ #if defined(CONFIG_ALL_PPC) extern int _machine; -extern int have_of; -#endif /* CONFIG_ALL_PPC */ /* what kind of prep workstation we are */ extern int _prep_type; + /* * This is used to identify the board type from a given PReP board * vendor. Board revision is also made available. @@ -570,6 +549,9 @@ extern unsigned char ucSystemType; extern unsigned char ucBoardRev; extern unsigned char ucBoardRevMaj, ucBoardRevMin; +#else +#define _machine 0 +#endif /* CONFIG_ALL_PPC */ struct task_struct; void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); @@ -681,26 +663,9 @@ /* In misc.c */ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); -#endif /* ndef ASSEMBLY*/ +#endif /* !__ASSEMBLY__ */ -#ifndef CONFIG_ALL_PPC -#if defined(CONFIG_APUS) -#define _machine _MACH_apus -#elif defined(CONFIG_GEMINI) -#define _machine _MACH_gemini -#elif defined(CONFIG_OAK) -#define _machine _MACH_oak -#elif defined(CONFIG_WALNUT) -#define _machine _MACH_walnut -#elif defined(CONFIG_8xx) -#define _machine _MACH_8xx -#elif defined(CONFIG_8260) -#define _machine _MACH_8260 -#else -#error "Machine not defined correctly" -#endif -#define have_of 0 -#endif /* !CONFIG_ALL_PPC */ +#define have_of (_machine == _MACH_chrp || _machine == _MACH_Pmac) #endif /* __ASM_PPC_PROCESSOR_H */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h --- v2.4.9/linux/include/asm-ppc/prom.h Mon Aug 27 12:41:48 2001 +++ linux/include/asm-ppc/prom.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.prom.h 1.16 07/25/01 14:11:37 trini + * BK Id: SCCS/s.prom.h 1.19 08/17/01 15:23:17 paulus */ /* * Definitions for talking to the Open Firmware PROM on @@ -18,9 +18,6 @@ extern char *prom_display_paths[]; extern unsigned int prom_num_displays; -#ifdef CONFIG_ALL_PPC -extern int have_of; -#endif struct address_range { unsigned int space; @@ -92,13 +89,6 @@ extern void print_properties(struct device_node *node); extern int call_rtas(const char *service, int nargs, int nret, unsigned long *outputs, ...); -extern void prom_drawstring(const char *c); -extern void prom_drawhex(unsigned long v); -extern void prom_drawchar(char c); - -extern void map_bootx_text(void); -extern void bootx_update_display(unsigned long phys, int width, int height, - int depth, int pitch); /* * When we call back to the Open Firmware client interface, we usually diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/residual.h linux/include/asm-ppc/residual.h --- v2.4.9/linux/include/asm-ppc/residual.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/residual.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.residual.h 1.5 05/17/01 18:14:25 cort + * BK Id: SCCS/s.residual.h 1.8 08/09/01 09:11:24 trini */ /* 7/18/95 */ /*----------------------------------------------------------------------------*/ @@ -29,7 +29,7 @@ /* Public structures... */ /*----------------------------------------------------------------------------*/ -#include "pnp.h" +#include typedef enum _L1CACHE_TYPE { NoneCAC = 0, diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/rpxclassic.h linux/include/asm-ppc/rpxclassic.h --- v2.4.9/linux/include/asm-ppc/rpxclassic.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/rpxclassic.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.rpxclassic.h 1.8 05/17/01 18:14:25 cort + * BK Id: SCCS/s.rpxclassic.h 1.11 08/17/01 15:23:17 paulus */ /* @@ -99,10 +99,6 @@ /* We don't use the 8259. */ #define NR_8259_INTS 0 - -/* Machine type -*/ -#define _MACH_8xx (_MACH_classic) #endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/rpxlite.h linux/include/asm-ppc/rpxlite.h --- v2.4.9/linux/include/asm-ppc/rpxlite.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/rpxlite.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.rpxlite.h 1.8 05/17/01 18:14:25 cort + * BK Id: SCCS/s.rpxlite.h 1.11 08/17/01 15:23:17 paulus */ /* @@ -79,10 +79,6 @@ /* We don't use the 8259. */ #define NR_8259_INTS 0 - -/* Machine type -*/ -#define _MACH_8xx (_MACH_rpxlite) #endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/smp.h linux/include/asm-ppc/smp.h --- v2.4.9/linux/include/asm-ppc/smp.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/smp.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.smp.h 1.9 05/17/01 18:14:25 cort + * BK Id: SCCS/s.smp.h 1.12 08/16/01 07:49:31 paulus */ /* smp.h: PPC specific SMP stuff. * @@ -32,12 +32,14 @@ extern unsigned long cpu_online_map; extern unsigned long smp_proc_in_lock[NR_CPUS]; extern volatile unsigned long cpu_callin_map[NR_CPUS]; +extern int smp_tb_synchronized; extern void smp_store_cpu_info(int id); extern void smp_send_tlb_invalidate(int); extern void smp_send_xmon_break(int cpu); struct pt_regs; extern void smp_message_recv(int, struct pt_regs *); +extern void smp_local_timer_interrupt(struct pt_regs *); #define NO_PROC_ID 0xFF /* No processor magic marker */ #define PROC_CHANGE_PENALTY 20 diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/spinlock.h linux/include/asm-ppc/spinlock.h --- v2.4.9/linux/include/asm-ppc/spinlock.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/spinlock.h Tue Aug 28 06:58:33 2001 @@ -1,33 +1,79 @@ /* - * BK Id: SCCS/s.spinlock.h 1.5 05/17/01 18:14:25 cort + * BK Id: SCCS/s.spinlock.h 1.9 08/21/01 16:07:48 trini */ -#ifdef __KERNEL__ #ifndef __ASM_SPINLOCK_H #define __ASM_SPINLOCK_H +#include + +#undef SPINLOCK_DEBUG + /* * Simple spin lock operations. */ typedef struct { volatile unsigned long lock; +#ifdef SPINLOCK_DEBUG volatile unsigned long owner_pc; volatile unsigned long owner_cpu; +#endif } spinlock_t; -#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, 0 } -#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0) -#define spin_unlock_wait(lp) do { barrier(); } while((lp)->lock) +#ifdef __KERNEL__ +#if SPINLOCK_DEBUG +#define SPINLOCK_DEBUG_INIT , 0, 0 +#else +#define SPINLOCK_DEBUG_INIT /* */ +#endif + +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 SPINLOCK_DEBUG_INIT } + +#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0) #define spin_is_locked(x) ((x)->lock != 0) +#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) + +#ifndef SPINLOCK_DEBUG + +static inline void spin_lock(spinlock_t *lock) +{ + unsigned long tmp; + + __asm__ __volatile__( + "b 1f # spin_lock\n\ +2: lwzx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + bne+ 2b\n\ +1: lwarx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + bne- 2b\n\ + stwcx. %2,0,%1\n\ + bne- 2b\n\ + isync" + : "=&r"(tmp) + : "r"(&lock->lock), "r"(1) + : "cr0", "memory"); +} + +static inline void spin_unlock(spinlock_t *lock) +{ + __asm__ __volatile__("eieio # spin_unlock": : :"memory"); + lock->lock = 0; +} + +#define spin_trylock(lock) (!test_and_set_bit(0,(lock))) + +#else extern void _spin_lock(spinlock_t *lock); extern void _spin_unlock(spinlock_t *lock); extern int spin_trylock(spinlock_t *lock); +extern unsigned long __spin_trylock(volatile unsigned long *lock); #define spin_lock(lp) _spin_lock(lp) #define spin_unlock(lp) _spin_unlock(lp) -extern unsigned long __spin_trylock(volatile unsigned long *lock); +#endif /* * Read-write spinlocks, allowing multiple readers @@ -41,12 +87,85 @@ */ typedef struct { volatile unsigned long lock; +#ifdef SPINLOCK_DEBUG volatile unsigned long owner_pc; +#endif } rwlock_t; -#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } +#if SPINLOCK_DEBUG +#define RWLOCK_DEBUG_INIT , 0 +#else +#define RWLOCK_DEBUG_INIT /* */ +#endif + +#define RW_LOCK_UNLOCKED (rwlock_t) { 0 RWLOCK_DEBUG_INIT } #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0) +#ifndef SPINLOCK_DEBUG + +static __inline__ void read_lock(rwlock_t *rw) +{ + unsigned int tmp; + + __asm__ __volatile__( + "b 2f # read_lock\n\ +1: lwzx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + blt+ 1b\n\ +2: lwarx %0,0,%1\n\ + addic. %0,%0,1\n\ + ble- 1b\n\ + stwcx. %0,0,%1\n\ + bne- 2b\n\ + isync" + : "=&r"(tmp) + : "r"(&rw->lock) + : "cr0", "memory"); +} + +static __inline__ void read_unlock(rwlock_t *rw) +{ + unsigned int tmp; + + __asm__ __volatile__( + "eieio # read_unlock\n\ +1: lwarx %0,0,%1\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + : "=&r"(tmp) + : "r"(&rw->lock) + : "cr0", "memory"); +} + +static __inline__ void write_lock(rwlock_t *rw) +{ + unsigned int tmp; + + __asm__ __volatile__( + "b 2f # write_lock\n\ +1: lwzx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + bne+ 1b\n\ +2: lwarx %0,0,%1\n\ + cmpwi 0,%0,0\n\ + bne- 1b\n\ + stwcx. %2,0,%1\n\ + bne- 2b\n\ + isync" + : "=&r"(tmp) + : "r"(&rw->lock), "r"(-1) + : "cr0", "memory"); +} + +static __inline__ void write_unlock(rwlock_t *rw) +{ + __asm__ __volatile__("eieio # write_unlock": : :"memory"); + rw->lock = 0; +} + +#else + extern void _read_lock(rwlock_t *rw); extern void _read_unlock(rwlock_t *rw); extern void _write_lock(rwlock_t *rw); @@ -56,6 +175,8 @@ #define write_lock(rw) _write_lock(rw) #define write_unlock(rw) _write_unlock(rw) #define read_unlock(rw) _read_unlock(rw) + +#endif #endif /* __ASM_SPINLOCK_H */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h --- v2.4.9/linux/include/asm-ppc/system.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/system.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.system.h 1.10 05/17/01 18:14:26 cort + * BK Id: SCCS/s.system.h 1.14 08/20/01 14:34:41 paulus */ /* * Copyright (C) 1999 Cort Dougan @@ -55,9 +55,13 @@ extern void flush_instruction_cache(void); extern void hard_reset_now(void); extern void poweroff_now(void); -extern int _get_PVR(void); +#ifdef CONFIG_6xx extern long _get_L2CR(void); extern void _set_L2CR(unsigned long); +#else +#define _get_L2CR() 0 +#define _set_L2CR(val) do { } while(0) +#endif extern void via_cuda_init(void); extern void pmac_nvram_init(void); extern void read_rtc_time(void); diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/time.h linux/include/asm-ppc/time.h --- v2.4.9/linux/include/asm-ppc/time.h Tue Jul 3 17:08:21 2001 +++ linux/include/asm-ppc/time.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.time.h 1.13 06/27/01 14:49:58 trini + * BK Id: SCCS/s.time.h 1.15 08/16/01 07:49:31 paulus */ /* * Common time prototypes and such for all ppc machines. @@ -74,6 +74,13 @@ unsigned long tbl; asm volatile("mftbu %0" : "=r" (tbl)); return tbl; +} + +extern __inline__ void set_tb(unsigned int upper, unsigned int lower) +{ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, upper); + mtspr(SPRN_TBWL, lower); } extern __inline__ unsigned long get_rtcl(void) { diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/timex.h linux/include/asm-ppc/timex.h --- v2.4.9/linux/include/asm-ppc/timex.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/timex.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.timex.h 1.5 05/17/01 18:14:26 cort + * BK Id: SCCS/s.timex.h 1.8 08/15/01 22:43:07 paulus */ /* * linux/include/asm-ppc/timex.h @@ -11,6 +11,7 @@ #define _ASMppc_TIMEX_H #include +#include #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ #define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ @@ -23,23 +24,25 @@ /* * For the "cycle" counter we use the timebase lower half. * Currently only used on SMP. - * - * Since SMP kernels won't run on the PPC601 CPU (which doesn't have - * the timebase register) anyway, we don't bother checking the CPU version. */ extern cycles_t cacheflush_time; static inline cycles_t get_cycles(void) { -#ifdef CONFIG_SMP - cycles_t ret; + cycles_t ret = 0; - __asm__("mftb %0" : "=r" (ret) : ); + __asm__ __volatile__( + "98: mftb %0\n" + "99:\n" + ".section __ftr_fixup,\"a\"\n" + " .long %1\n" + " .long 0\n" + " .long 98b\n" + " .long 99b\n" + ".previous" + : "=r" (ret) : "i" (CPU_FTR_601)); return ret; -#else - return 0; -#endif } #endif diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/tqm8xx.h linux/include/asm-ppc/tqm8xx.h --- v2.4.9/linux/include/asm-ppc/tqm8xx.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/tqm8xx.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.tqm8xx.h 1.6 05/17/01 18:14:26 cort + * BK Id: SCCS/s.tqm8xx.h 1.7 08/17/01 15:23:17 paulus */ /* * A collection of structures, addresses, and values associated with @@ -68,14 +68,5 @@ /* We don't use the 8259. */ #define NR_8259_INTS 0 - -/* Generic 8xx type -*/ -#if defined(CONFIG_TQM8xxL) -#define _MACH_8xx (_MACH_tqm8xxL) -#endif -#if defined(CONFIG_TQM860) -#define _MACH_8xx (_MACH_tqm860) -#endif #endif /* __MACH_TQM8xx_DEFS */ diff -u --recursive --new-file v2.4.9/linux/include/asm-ppc/uninorth.h linux/include/asm-ppc/uninorth.h --- v2.4.9/linux/include/asm-ppc/uninorth.h Mon May 21 15:02:06 2001 +++ linux/include/asm-ppc/uninorth.h Tue Aug 28 06:58:33 2001 @@ -1,5 +1,5 @@ /* - * BK Id: SCCS/s.uninorth.h 1.7 05/17/01 18:14:26 cort + * BK Id: SCCS/s.uninorth.h 1.11 08/19/01 22:23:04 paulus */ /* * uninorth.h: definitions for using the "UniNorth" host bridge chip @@ -31,6 +31,52 @@ #define UNI_N_CFG_GART_ENABLE 0x00000100 #define UNI_N_CFG_GART_2xRESET 0x00010000 +/* My understanding of UniNorth AGP as of UniNorth rev 1.0x, + * revision 1.5 (x4 AGP) may need further changes. + * + * AGP_BASE register contains the base address of the AGP aperture on + * the AGP bus. It doesn't seem to be visible to the CPU as of UniNorth 1.x, + * even if decoding of this address range is enabled in the address select + * register. Apparently, the only supported bases are 256Mb multiples + * (high 4 bits of that register). + * + * GART_BASE register appear to contain the physical address of the GART + * in system memory in the high address bits (page aligned), and the + * GART size in the low order bits (number of GART pages) + * + * The GART format itself is one 32bits word per physical memory page. + * This word contains, in little-endian format (!!!), the physical address + * of the page in the high bits, and what appears to be an "enable" bit + * in the LSB bit (0) that must be set to 1 when the entry is valid. + * + * Obviously, the GART is not cache coherent and so any change to it + * must be flushed to memory (or maybe just make the GART space non + * cachable). AGP memory itself doens't seem to be cache coherent neither. + * + * In order to invalidate the GART (which is probably necessary to inval + * the bridge internal TLBs), the following sequence has to be written, + * in order, to the GART_CTRL register: + * + * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL + * UNI_N_CFG_GART_ENABLE + * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET + * UNI_N_CFG_GART_ENABLE + * + * As far as AGP "features" are concerned, it looks like fast write may + * not be supported but this has to be confirmed. + * + * Turning on AGP seem to require a double invalidate operation, one before + * setting the AGP command register, on after. + * + * Turning off AGP seems to require the following sequence: first wait + * for the AGP to be idle by reading the internal status register, then + * write in that order to the GART_CTRL register: + * + * UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL + * 0 + * UNI_N_CFG_GART_2xRESET + * 0 + */ /* * Uni-N memory mapped reg. definitions diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc/keyboard.h linux/include/asm-sparc/keyboard.h --- v2.4.9/linux/include/asm-sparc/keyboard.h Mon Dec 20 22:05:52 1999 +++ linux/include/asm-sparc/keyboard.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: keyboard.h,v 1.3 1999/11/23 08:56:44 davem Exp $ +/* $Id: keyboard.h,v 1.7 2001/08/18 09:40:46 davem Exp $ * linux/include/asm-sparc/keyboard.h * * sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be) @@ -13,7 +13,9 @@ #ifdef __KERNEL__ +#include #include +#include #include #define KEYBOARD_IRQ 13 diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h --- v2.4.9/linux/include/asm-sparc64/floppy.h Wed May 16 10:31:27 2001 +++ linux/include/asm-sparc64/floppy.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: floppy.h,v 1.30 2001/05/11 07:05:38 davem Exp $ +/* $Id: floppy.h,v 1.31 2001/08/22 17:46:31 davem Exp $ * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -268,8 +268,15 @@ static struct linux_ebus_dma *sun_pci_fd_ebus_dma; static struct pci_dev *sun_pci_ebus_dev; static int sun_pci_broken_drive = -1; -static unsigned int sun_pci_dma_addr = -1U; -static int sun_pci_dma_len, sun_pci_dma_direction; + +struct sun_pci_dma_op { + unsigned int addr; + int len; + int direction; + char *buf; +}; +static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL}; +static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL}; extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs); @@ -339,6 +346,29 @@ { unsigned int dcsr; + if((NULL == sun_pci_dma_pending.buf) || + (0 == sun_pci_dma_pending.len) || + (0 == sun_pci_dma_pending.direction)) { + goto enable; /* TODO: BUG() */ + } + + sun_pci_dma_current.buf = sun_pci_dma_pending.buf; + sun_pci_dma_current.len = sun_pci_dma_pending.len; + sun_pci_dma_current.direction = sun_pci_dma_pending.direction; + + sun_pci_dma_pending.buf = NULL; + sun_pci_dma_pending.len = 0; + sun_pci_dma_pending.direction = 0; + sun_pci_dma_pending.addr = -1U; + + sun_pci_dma_current.addr = + pci_map_single( sun_pci_ebus_dev, + sun_pci_dma_current.buf, + sun_pci_dma_current.len, + sun_pci_dma_current.direction); + writel(sun_pci_dma_current.addr, &sun_pci_fd_ebus_dma->dacr); + +enable: dcsr = readl(&sun_pci_fd_ebus_dma->dcsr); dcsr |= EBUS_DCSR_EN_DMA; writel(dcsr, &sun_pci_fd_ebus_dma->dcsr); @@ -362,12 +392,12 @@ writel(dcsr, &sun_pci_fd_ebus_dma->dcsr); } } - if (sun_pci_dma_addr != -1U) + if (sun_pci_dma_current.addr != -1U) pci_unmap_single(sun_pci_ebus_dev, - sun_pci_dma_addr, - sun_pci_dma_len, - sun_pci_dma_direction); - sun_pci_dma_addr = -1U; + sun_pci_dma_current.addr, + sun_pci_dma_current.len, + sun_pci_dma_current.direction); + sun_pci_dma_current.addr = -1U; } static void sun_pci_fd_set_dma_mode(int mode) @@ -387,29 +417,23 @@ */ if (mode == DMA_MODE_WRITE) { dcsr &= ~(EBUS_DCSR_WRITE); - sun_pci_dma_direction = PCI_DMA_TODEVICE; + sun_pci_dma_pending.direction = PCI_DMA_TODEVICE; } else { dcsr |= EBUS_DCSR_WRITE; - sun_pci_dma_direction = PCI_DMA_FROMDEVICE; + sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE; } writel(dcsr, &sun_pci_fd_ebus_dma->dcsr); } static void sun_pci_fd_set_dma_count(int length) { - sun_pci_dma_len = length; + sun_pci_dma_pending.len = length; writel(length, &sun_pci_fd_ebus_dma->dbcr); } static void sun_pci_fd_set_dma_addr(char *buffer) { - unsigned int addr; - - addr = sun_pci_dma_addr = pci_map_single(sun_pci_ebus_dev, - buffer, - sun_pci_dma_len, - sun_pci_dma_direction); - writel(addr, &sun_pci_fd_ebus_dma->dacr); + sun_pci_dma_pending.buf = buffer; } static unsigned int sun_pci_get_dma_residue(void) @@ -719,7 +743,7 @@ sun_fdops.fd_inb = sun_pci_fd_inb; sun_fdops.fd_outb = sun_pci_fd_outb; - use_virtual_dma = 0; + can_use_virtual_dma = use_virtual_dma = 0; sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma; sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma; sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode; @@ -796,9 +820,9 @@ ns87303_modify(config, ASC, ASC_DRV2_SEL, 0); ns87303_modify(config, FCR, 0, FCR_LDE); - cfg = sun_floppy_types[0]; + config = sun_floppy_types[0]; sun_floppy_types[0] = sun_floppy_types[1]; - sun_floppy_types[1] = cfg; + sun_floppy_types[1] = config; if (sun_pci_broken_drive != -1) { sun_pci_broken_drive = 1 - sun_pci_broken_drive; diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc64/keyboard.h linux/include/asm-sparc64/keyboard.h --- v2.4.9/linux/include/asm-sparc64/keyboard.h Mon Aug 27 12:41:48 2001 +++ linux/include/asm-sparc64/keyboard.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: keyboard.h,v 1.4 2001/08/13 14:40:07 davem Exp $ +/* $Id: keyboard.h,v 1.5 2001/08/18 09:40:46 davem Exp $ * linux/include/asm-sparc64/keyboard.h * * Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be) @@ -25,7 +25,6 @@ char raw_mode); extern char pcikbd_unexpected_up(unsigned char keycode); extern void pcikbd_leds(unsigned char leds); -extern int pcikbd_rate(struct kbd_repeat *rep); extern void pcikbd_init_hw(void); extern unsigned char pcikbd_sysrq_xlate[128]; @@ -34,7 +33,6 @@ #define kbd_translate pcikbd_translate #define kbd_unexpected_up pcikbd_unexpected_up #define kbd_leds pcikbd_leds -#define kbd_rate pcikbd_rate #define kbd_init_hw pcikbd_init_hw #define kbd_sysrq_xlate pcikbd_sysrq_xlate #define kbd_init pcikbd_init diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h --- v2.4.9/linux/include/asm-sparc64/mmu_context.h Mon Aug 27 12:41:48 2001 +++ linux/include/asm-sparc64/mmu_context.h Tue Aug 28 07:09:44 2001 @@ -1,24 +1,11 @@ -/* $Id: mmu_context.h,v 1.50 2001/08/13 20:24:34 kanoj Exp $ */ +/* $Id: mmu_context.h,v 1.51 2001/08/17 04:55:09 kanoj Exp $ */ #ifndef __SPARC64_MMU_CONTEXT_H #define __SPARC64_MMU_CONTEXT_H /* Derived heavily from Linus's Alpha/AXP ASN code... */ -#ifndef __ASSEMBLY__ - -#include -#include -#include #include -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) -{ -} - -extern spinlock_t ctx_alloc_lock; -extern unsigned long tlb_context_cache; -extern unsigned long mmu_context_bmap[]; - /* * For the 8k pagesize kernel, use only 10 hw context bits to optimize some shifts in * the fast tlbmiss handlers, instead of all 13 bits (specifically for vpte offset @@ -28,9 +15,25 @@ */ #if PAGE_SHIFT == 13 #define CTX_VERSION_SHIFT 10 +#define TAG_CONTEXT_BITS 0x3ff #else #define CTX_VERSION_SHIFT 12 +#define TAG_CONTEXT_BITS 0xfff #endif + +#ifndef __ASSEMBLY__ + +#include +#include +#include + +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) +{ +} + +extern spinlock_t ctx_alloc_lock; +extern unsigned long tlb_context_cache; +extern unsigned long mmu_context_bmap[]; #define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT) #define CTX_FIRST_VERSION ((1UL << CTX_VERSION_SHIFT) + 1UL) diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc64/pgalloc.h linux/include/asm-sparc64/pgalloc.h --- v2.4.9/linux/include/asm-sparc64/pgalloc.h Thu Apr 26 22:17:26 2001 +++ linux/include/asm-sparc64/pgalloc.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pgalloc.h,v 1.20 2001/04/26 02:36:36 davem Exp $ */ +/* $Id: pgalloc.h,v 1.21 2001/08/22 22:16:56 kanoj Exp $ */ #ifndef _SPARC64_PGALLOC_H #define _SPARC64_PGALLOC_H @@ -64,7 +64,7 @@ #define flush_tlb_range(__mm, start, end) \ do { if(CTX_VALID((__mm)->context)) { \ unsigned long __start = (start)&PAGE_MASK; \ - unsigned long __end = (end)&PAGE_MASK; \ + unsigned long __end = PAGE_ALIGN(end); \ __flush_tlb_range(CTX_HWBITS((__mm)->context), __start, \ SECONDARY_CONTEXT, __end, PAGE_SIZE, \ (__end - __start)); \ diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h --- v2.4.9/linux/include/asm-sparc64/pgtable.h Mon Aug 27 12:41:48 2001 +++ linux/include/asm-sparc64/pgtable.h Tue Aug 28 07:09:44 2001 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.141 2001/08/13 20:24:34 kanoj Exp $ +/* $Id: pgtable.h,v 1.143 2001/08/22 22:16:56 kanoj Exp $ * pgtable.h: SpitFire page table operations. * * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -18,16 +18,6 @@ #include #include -#ifndef __ASSEMBLY__ - -#define PG_dcache_dirty PG_arch_1 - -/* Certain architectures need to do special things when pte's - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) - /* XXX All of this needs to be rethought so we can take advantage * XXX cheetah's full 64-bit virtual address space, ie. no more hole * XXX in the middle like on spitfire. -DaveM @@ -55,6 +45,16 @@ #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) +#ifndef __ASSEMBLY__ + +#define PG_dcache_dirty PG_arch_1 + +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) + /* Entries per page directory level. */ #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) @@ -72,9 +72,6 @@ #define USER_PTRS_PER_PGD ((const int)((current->thread.flags & SPARC_FLAG_32BIT) ? \ (1) : (PTRS_PER_PGD))) #define FIRST_USER_PGD_NR 0 - -#define PTE_TABLE_SIZE 0x2000 /* 1024 entries 8 bytes each */ -#define PMD_TABLE_SIZE 0x2000 /* 2048 entries 4 bytes each */ /* NOTE: TLB miss handlers depend heavily upon where this is. */ #define VMALLOC_START 0x0000000140000000UL diff -u --recursive --new-file v2.4.9/linux/include/asm-sparc64/vaddrs.h linux/include/asm-sparc64/vaddrs.h --- v2.4.9/linux/include/asm-sparc64/vaddrs.h Tue Aug 4 16:03:35 1998 +++ linux/include/asm-sparc64/vaddrs.h Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -/* $Id: vaddrs.h,v 1.10 1998/05/14 13:36:01 jj Exp $ */ -#ifndef _SPARC64_VADDRS_H -#define _SPARC64_VADDRS_H - -/* asm-sparc64/vaddrs.h: Here will be define the virtual addresses at - * which important I/O addresses will be mapped. - * For instance the timer register virtual address - * is defined here. - * - * Copyright (C) 1995,1998 David S. Miller (davem@caip.rutgers.edu) - */ - -/* Everything here must be in the first kernel PGD. */ -#define DVMA_VADDR 0x0000000100000000ULL /* Base area of the DVMA on suns */ -#define DVMA_LEN 0x0000000040000000ULL /* Size of the DVMA address space */ -#define DVMA_END 0x0000000140000000ULL -#define MODULES_VADDR 0x0000000001000000ULL /* Where to map modules */ -#define MODULES_LEN 0x000000007f000000ULL -#define MODULES_END 0x0000000080000000ULL - -#endif /* !(_SPARC_VADDRS_H) */ - diff -u --recursive --new-file v2.4.9/linux/include/linux/agp_backend.h linux/include/linux/agp_backend.h --- v2.4.9/linux/include/linux/agp_backend.h Tue Jul 3 17:08:21 2001 +++ linux/include/linux/agp_backend.h Mon Aug 27 07:40:33 2001 @@ -85,6 +85,8 @@ size_t aper_size; int max_memory; /* In pages */ int current_memory; + int cant_use_aperture; + unsigned long page_mask; } agp_kern_info; /* diff -u --recursive --new-file v2.4.9/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.4.9/linux/include/linux/fs.h Mon Aug 27 12:41:48 2001 +++ linux/include/linux/fs.h Tue Aug 28 11:01:01 2001 @@ -89,12 +89,7 @@ #define FS_NO_PRELIM 4 /* prevent preloading of dentries, even if * FS_NO_DCACHE is not set. */ -#define FS_SINGLE 8 /* - * Filesystem that can have only one superblock; - * kernel-wide vfsmnt is placed in ->kern_mnt by - * kern_mount() which must be called _after_ - * register_filesystem(). - */ +#define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon @@ -665,6 +660,7 @@ extern spinlock_t sb_lock; #define sb_entry(list) list_entry((list), struct super_block, s_list) +#define S_BIAS (1<<30) struct super_block { struct list_head s_list; /* Keep this first */ kdev_t s_dev; @@ -688,6 +684,7 @@ struct list_head s_files; struct block_device *s_bdev; + struct list_head s_instances; struct quota_mount_options s_dquot; /* Diskquota specific options */ union { @@ -913,8 +910,8 @@ int fs_flags; struct super_block *(*read_super) (struct super_block *, void *, int); struct module *owner; - struct vfsmount *kern_mnt; /* For kernel mount, if it's FS_SINGLE fs */ struct file_system_type * next; + struct list_head fs_supers; }; #define DECLARE_FSTYPE(var,type,read,flags) \ @@ -1147,7 +1144,7 @@ buffer_insert_inode_queue(bh, inode); } -extern void balance_dirty(kdev_t); +extern void balance_dirty(void); extern int check_disk_change(kdev_t); extern int invalidate_inodes(struct super_block *); extern int invalidate_device(kdev_t, int); diff -u --recursive --new-file v2.4.9/linux/include/linux/highmem.h linux/include/linux/highmem.h --- v2.4.9/linux/include/linux/highmem.h Tue Aug 7 12:48:43 2001 +++ linux/include/linux/highmem.h Mon Aug 27 13:21:43 2001 @@ -45,8 +45,9 @@ /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ static inline void clear_user_highpage(struct page *page, unsigned long vaddr) { - clear_user_page(kmap(page), vaddr); - kunmap(page); + void *addr = kmap_atomic(page, KM_USER0); + clear_user_page(addr, vaddr); + kunmap_atomic(addr, KM_USER0); } static inline void clear_highpage(struct page *page) @@ -85,11 +86,11 @@ { char *vfrom, *vto; - vfrom = kmap(from); - vto = kmap(to); + vfrom = kmap_atomic(from, KM_USER0); + vto = kmap_atomic(to, KM_USER1); copy_user_page(vto, vfrom, vaddr); - kunmap(from); - kunmap(to); + kunmap_atomic(vfrom, KM_USER0); + kunmap_atomic(vto, KM_USER1); } static inline void copy_highpage(struct page *to, struct page *from) diff -u --recursive --new-file v2.4.9/linux/include/linux/kernel.h linux/include/linux/kernel.h --- v2.4.9/linux/include/linux/kernel.h Mon Aug 27 12:41:48 2001 +++ linux/include/linux/kernel.h Mon Aug 27 21:15:58 2001 @@ -10,6 +10,7 @@ #include #include #include +#include /* Optimization barrier */ /* The "volatile" is due to gcc bugs */ @@ -61,6 +62,8 @@ extern long long simple_strtoll(const char *,char **,unsigned int); extern int sprintf(char * buf, const char * fmt, ...); extern int vsprintf(char *buf, const char *, va_list); +extern int snprintf(char * buf, size_t size, const char *fmt, ...); +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); extern int get_option(char **str, int *pint); extern char *get_options(char *str, int nints, int *ints); extern unsigned long long memparse(char *ptr, char **retptr); @@ -113,9 +116,9 @@ ((unsigned char *)&addr)[0] #define min(type,x,y) \ - ({ type __x = (x), __y = (y); __x < __y ? __x: __y; }) + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) #define max(type,x,y) \ - ({ type __x = (x), __y = (y); __x > __y ? __x: __y; }) + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.4.9/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.4.9/linux/include/linux/mm.h Tue Aug 7 12:48:43 2001 +++ linux/include/linux/mm.h Mon Aug 27 21:03:37 2001 @@ -536,17 +536,20 @@ /* Action modifiers - doesn't change the zoning */ #define __GFP_WAIT 0x10 /* Can wait and reschedule? */ #define __GFP_HIGH 0x20 /* Should access emergency pools? */ -#define __GFP_IO 0x40 /* Can start physical IO? */ -#define __GFP_FS 0x80 /* Can call down to low-level FS? */ +#define __GFP_IO 0x40 /* Can start low memory physical IO? */ +#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */ +#define __GFP_FS 0x100 /* Can call down to low-level FS? */ +#define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO) #define GFP_NOIO (__GFP_HIGH | __GFP_WAIT) -#define GFP_NOFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO) +#define GFP_NOFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO) #define GFP_ATOMIC (__GFP_HIGH) -#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_FS) -#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HIGHMEM) -#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_FS) -#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_FS) -#define GFP_KSWAPD ( __GFP_IO | __GFP_FS) +#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) +#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO \ + | __GFP_FS | __GFP_HIGHMEM) +#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) +#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS) +#define GFP_KSWAPD ( __GFP_IO | __GFP_HIGHIO | __GFP_FS) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ diff -u --recursive --new-file v2.4.9/linux/include/linux/ntfs_fs.h linux/include/linux/ntfs_fs.h --- v2.4.9/linux/include/linux/ntfs_fs.h Mon Mar 13 12:35:39 2000 +++ linux/include/linux/ntfs_fs.h Tue Aug 28 06:57:18 2001 @@ -1,3 +1,21 @@ #ifndef _LINUX_NTFS_FS_H #define _LINUX_NTFS_FS_H + +#include + +#define NTFS_SECTOR_BITS 9 +#define NTFS_SECTOR_SIZE 512 + +/* + * Attribute flags (16-bit). + */ +typedef enum { + ATTR_IS_COMPRESSED = cpu_to_le16(0x0001), + ATTR_COMPRESSION_MASK = cpu_to_le16(0x00ff), /* Compression method + * mask. Also, first + * illegal value. */ + ATTR_IS_ENCRYPTED = cpu_to_le16(0x4000), + ATTR_IS_SPARSE = cpu_to_le16(0x8000), +} __attribute__ ((__packed__)) ATTR_FLAGS; + #endif diff -u --recursive --new-file v2.4.9/linux/include/linux/ntfs_fs_i.h linux/include/linux/ntfs_fs_i.h --- v2.4.9/linux/include/linux/ntfs_fs_i.h Wed Jul 25 17:10:26 2001 +++ linux/include/linux/ntfs_fs_i.h Tue Aug 28 06:57:18 2001 @@ -1,6 +1,8 @@ #ifndef _LINUX_NTFS_FS_I_H #define _LINUX_NTFS_FS_I_H +#include + /* Forward declarations, to keep number of mutual includes low */ struct ntfs_attribute; struct ntfs_sb_info; diff -u --recursive --new-file v2.4.9/linux/include/linux/ntfs_fs_sb.h linux/include/linux/ntfs_fs_sb.h --- v2.4.9/linux/include/linux/ntfs_fs_sb.h Mon Aug 27 12:41:48 2001 +++ linux/include/linux/ntfs_fs_sb.h Tue Aug 28 06:57:18 2001 @@ -1,7 +1,7 @@ #ifndef _LINUX_NTFS_FS_SB_H #define _LINUX_NTFS_FS_SB_H -typedef __s64 LCN; +#include struct ntfs_sb_info{ /* Configuration provided by user at mount time. */ @@ -10,6 +10,8 @@ ntmode_t umask; void *nls_map; unsigned int ngt; + char mft_zone_multiplier; + ntfs_cluster_t mft_zone_end; /* Configuration provided by user with the ntfstools. * FIXME: This is no longer possible. What is this good for? (AIA) */ ntfs_size_t partition_bias; /* For access to underlying device. */ @@ -36,7 +38,9 @@ int index_clusters_per_record; int index_record_size; int index_record_size_bits; - LCN mft_lcn; + ntfs_cluster_t nr_clusters; + ntfs_cluster_t mft_lcn; + ntfs_cluster_t mft_mirr_lcn; /* Data read from special files. */ unsigned char *mft; unsigned short *upcase; diff -u --recursive --new-file v2.4.9/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h --- v2.4.9/linux/include/linux/pci_ids.h Mon Aug 27 12:41:48 2001 +++ linux/include/linux/pci_ids.h Mon Aug 27 08:56:31 2001 @@ -985,6 +985,7 @@ #define PCI_VENDOR_ID_PHILIPS 0x1131 #define PCI_DEVICE_ID_PHILIPS_SAA7145 0x7145 #define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146 +#define PCI_DEVICE_ID_PHILIPS_SAA9730 0x9730 #define PCI_VENDOR_ID_EICON 0x1133 #define PCI_DEVICE_ID_EICON_DIVA20PRO 0xe001 @@ -1098,6 +1099,9 @@ #define PCI_VENDOR_ID_GALILEO 0x11ab #define PCI_DEVICE_ID_GALILEO_GT64011 0x4146 +#define PCI_DEVICE_ID_GALILEO_GT64111 0x4146 +#define PCI_DEVICE_ID_GALILEO_GT96100 0x9652 +#define PCI_DEVICE_ID_GALILEO_GT96100A 0x9653 #define PCI_VENDOR_ID_LITEON 0x11ad #define PCI_DEVICE_ID_LITEON_LNE100TX 0x0002 @@ -1227,6 +1231,10 @@ #define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371 #define PCI_VENDOR_ID_ROCKWELL 0x127A + +#define PCI_VENDOR_ID_ITE 0x1283 +#define PCI_DEVICE_ID_ITE_IT8172G 0x8172 +#define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801 #define PCI_VENDOR_ID_ITE 0x1283 #define PCI_DEVICE_ID_ITE_IT8172G 0x8172 diff -u --recursive --new-file v2.4.9/linux/include/linux/slab.h linux/include/linux/slab.h --- v2.4.9/linux/include/linux/slab.h Tue Aug 7 12:48:43 2001 +++ linux/include/linux/slab.h Mon Aug 27 21:03:37 2001 @@ -17,13 +17,14 @@ /* flags for kmem_cache_alloc() */ #define SLAB_NOFS GFP_NOFS #define SLAB_NOIO GFP_NOIO +#define SLAB_NOHIGHIO GFP_NOHIGHIO #define SLAB_ATOMIC GFP_ATOMIC #define SLAB_USER GFP_USER #define SLAB_KERNEL GFP_KERNEL #define SLAB_NFS GFP_NFS #define SLAB_DMA GFP_DMA -#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS) +#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_HIGHIO|__GFP_FS) #define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */ /* flags to pass to kmem_cache_create(). diff -u --recursive --new-file v2.4.9/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.4.9/linux/include/linux/sysctl.h Tue Aug 7 12:48:42 2001 +++ linux/include/linux/sysctl.h Tue Aug 28 07:09:44 2001 @@ -281,6 +281,8 @@ NET_TCP_APP_WIN=86, NET_TCP_ADV_WIN_SCALE=87, NET_IPV4_NONLOCAL_BIND=88, + NET_IPV4_ICMP_RATELIMIT=89, + NET_IPV4_ICMP_RATEMASK=90 }; enum { diff -u --recursive --new-file v2.4.9/linux/include/linux/vt_kern.h linux/include/linux/vt_kern.h --- v2.4.9/linux/include/linux/vt_kern.h Tue Aug 7 12:51:23 2001 +++ linux/include/linux/vt_kern.h Tue Aug 28 07:09:44 2001 @@ -8,6 +8,7 @@ #include #include +#include /* * Presently, a lot of graphics programs do not restore the contents of @@ -31,6 +32,7 @@ } *vt_cons[MAX_NR_CONSOLES]; extern void (*kd_mksound)(unsigned int hz, unsigned int ticks); +extern int (*kbd_rate)(struct kbd_repeat *rep); /* console.c */ diff -u --recursive --new-file v2.4.9/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.4.9/linux/kernel/ksyms.c Mon Aug 27 12:41:49 2001 +++ linux/kernel/ksyms.c Mon Aug 27 21:15:58 2001 @@ -434,6 +434,7 @@ /* process management */ EXPORT_SYMBOL(complete_and_exit); EXPORT_SYMBOL(__wake_up); +EXPORT_SYMBOL(__wake_up_sync); EXPORT_SYMBOL(wake_up_process); EXPORT_SYMBOL(sleep_on); EXPORT_SYMBOL(sleep_on_timeout); @@ -457,7 +458,9 @@ EXPORT_SYMBOL(panic); EXPORT_SYMBOL(printk); EXPORT_SYMBOL(sprintf); +EXPORT_SYMBOL(snprintf); EXPORT_SYMBOL(vsprintf); +EXPORT_SYMBOL(vsnprintf); EXPORT_SYMBOL(kdevname); EXPORT_SYMBOL(bdevname); EXPORT_SYMBOL(cdevname); diff -u --recursive --new-file v2.4.9/linux/kernel/signal.c linux/kernel/signal.c --- v2.4.9/linux/kernel/signal.c Wed Jan 3 20:45:26 2001 +++ linux/kernel/signal.c Mon Aug 27 08:58:52 2001 @@ -242,16 +242,16 @@ #endif sig = next_signal(current, mask); - if (current->notifier) { - if (sigismember(current->notifier_mask, sig)) { - if (!(current->notifier)(current->notifier_data)) { - current->sigpending = 0; - return 0; + if (sig) { + if (current->notifier) { + if (sigismember(current->notifier_mask, sig)) { + if (!(current->notifier)(current->notifier_data)) { + current->sigpending = 0; + return 0; + } } } - } - if (sig) { if (!collect_signal(sig, ¤t->pending, info)) sig = 0; diff -u --recursive --new-file v2.4.9/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.4.9/linux/kernel/sysctl.c Sun Aug 12 13:28:01 2001 +++ linux/kernel/sysctl.c Tue Aug 28 07:11:33 2001 @@ -83,8 +83,8 @@ extern int sysctl_userprocess_debug; #endif -#ifdef __powerpc__ -extern unsigned long htab_reclaim_on, zero_paged_on, powersave_nap; +#ifdef CONFIG_PPC32 +extern unsigned long zero_paged_on, powersave_nap; int proc_dol2crvec(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp); #endif @@ -178,9 +178,7 @@ {KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int), 0644, NULL, &proc_dointvec}, #endif -#ifdef __powerpc__ - {KERN_PPC_HTABRECLAIM, "htab-reclaim", &htab_reclaim_on, sizeof(int), - 0644, NULL, &proc_dointvec}, +#ifdef CONFIG_PPC32 {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int), 0644, NULL, &proc_dointvec}, {KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int), diff -u --recursive --new-file v2.4.9/linux/lib/Makefile linux/lib/Makefile --- v2.4.9/linux/lib/Makefile Wed Apr 25 13:31:03 2001 +++ linux/lib/Makefile Tue Aug 28 07:11:33 2001 @@ -8,7 +8,7 @@ L_TARGET := lib.a -export-objs := cmdline.o rwsem-spinlock.o rwsem.o +export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o diff -u --recursive --new-file v2.4.9/linux/lib/dec_and_lock.c linux/lib/dec_and_lock.c --- v2.4.9/linux/lib/dec_and_lock.c Fri Jul 7 16:22:48 2000 +++ linux/lib/dec_and_lock.c Tue Aug 28 07:11:33 2001 @@ -1,3 +1,4 @@ +#include #include #include @@ -34,4 +35,6 @@ spin_unlock(lock); return 0; } + +EXPORT_SYMBOL(atomic_dec_and_lock); #endif diff -u --recursive --new-file v2.4.9/linux/mm/filemap.c linux/mm/filemap.c --- v2.4.9/linux/mm/filemap.c Mon Aug 27 12:41:49 2001 +++ linux/mm/filemap.c Tue Aug 28 11:09:19 2001 @@ -2541,6 +2541,7 @@ while (count) { unsigned long index, offset; + long page_fault; char *kaddr; /* @@ -2574,15 +2575,15 @@ PAGE_BUG(page); } + kaddr = kmap(page); status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes); if (status) goto unlock; - kaddr = page_address(page); - status = __copy_from_user(kaddr+offset, buf, bytes); + page_fault = __copy_from_user(kaddr+offset, buf, bytes); flush_dcache_page(page); - if (status) - goto fail_write; status = mapping->a_ops->commit_write(file, page, offset, offset+bytes); + if (page_fault) + goto fail_write; if (!status) status = bytes; @@ -2593,6 +2594,7 @@ buf += status; } unlock: + kunmap(page); /* Mark it unlocked again and drop the page.. */ UnlockPage(page); check_used_once(page); @@ -2618,8 +2620,6 @@ return err; fail_write: status = -EFAULT; - ClearPageUptodate(page); - kunmap(page); goto unlock; } diff -u --recursive --new-file v2.4.9/linux/mm/highmem.c linux/mm/highmem.c --- v2.4.9/linux/mm/highmem.c Mon Aug 27 12:41:49 2001 +++ linux/mm/highmem.c Mon Aug 27 21:03:37 2001 @@ -321,7 +321,7 @@ struct page *page; repeat_alloc: - page = alloc_page(GFP_NOIO); + page = alloc_page(GFP_NOHIGHIO); if (page) return page; /* @@ -359,7 +359,7 @@ struct buffer_head *bh; repeat_alloc: - bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO); + bh = kmem_cache_alloc(bh_cachep, SLAB_NOHIGHIO); if (bh) return bh; /* diff -u --recursive --new-file v2.4.9/linux/mm/memory.c linux/mm/memory.c --- v2.4.9/linux/mm/memory.c Mon Aug 27 12:41:49 2001 +++ linux/mm/memory.c Sun Aug 26 20:32:18 2001 @@ -1119,6 +1119,7 @@ */ return pte_same(*page_table, orig_pte) ? -1 : 1; } + SetPageReferenced(page); } /* diff -u --recursive --new-file v2.4.9/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.4.9/linux/mm/page_alloc.c Mon Aug 27 12:41:49 2001 +++ linux/mm/page_alloc.c Tue Aug 28 07:09:44 2001 @@ -502,7 +502,8 @@ } /* No luck.. */ - printk(KERN_ERR "__alloc_pages: %lu-order allocation failed.\n", order); + printk(KERN_ERR "__alloc_pages: %lu-order allocation failed (gfp=0x%x/%i).\n", + order, gfp_mask, !!(current->flags & PF_MEMALLOC)); return NULL; } diff -u --recursive --new-file v2.4.9/linux/mm/shmem.c linux/mm/shmem.c --- v2.4.9/linux/mm/shmem.c Sun Aug 12 13:28:01 2001 +++ linux/mm/shmem.c Tue Aug 28 10:56:06 2001 @@ -1158,6 +1158,7 @@ #else static DECLARE_FSTYPE(tmpfs_fs_type, "tmpfs", shmem_read_super, FS_LITTER|FS_NOMOUNT); #endif +static struct vfsmount *shm_mnt; static int __init init_shmem_fs(void) { @@ -1181,6 +1182,7 @@ unregister_filesystem(&tmpfs_fs_type); return PTR_ERR(res); } + shm_mnt = res; /* The internal instance should not do size checking */ if ((error = shmem_set_size(&res->mnt_sb->u.shmem_sb, ULONG_MAX, ULONG_MAX))) @@ -1195,6 +1197,7 @@ unregister_filesystem(&shmem_fs_type); #endif unregister_filesystem(&tmpfs_fs_type); + mntput(shm_mnt); } module_init(init_shmem_fs) @@ -1292,7 +1295,7 @@ this.name = name; this.len = strlen(name); this.hash = 0; /* will go */ - root = tmpfs_fs_type.kern_mnt->mnt_root; + root = shm_mnt->mnt_root; dentry = d_alloc(root, &this); if (!dentry) return ERR_PTR(-ENOMEM); @@ -1310,7 +1313,7 @@ d_instantiate(dentry, inode); dentry->d_inode->i_size = size; shmem_truncate(inode); - file->f_vfsmnt = mntget(tmpfs_fs_type.kern_mnt); + file->f_vfsmnt = mntget(shm_mnt); file->f_dentry = dentry; file->f_op = &shmem_file_operations; file->f_mode = FMODE_WRITE | FMODE_READ; diff -u --recursive --new-file v2.4.9/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c --- v2.4.9/linux/net/appletalk/ddp.c Mon Aug 27 12:41:49 2001 +++ linux/net/appletalk/ddp.c Tue Aug 28 07:09:44 2001 @@ -752,7 +752,7 @@ /* ioctl calls. Shouldn't even need touching */ /* Device configuration ioctl calls */ -int atif_ioctl(int cmd, void *arg) +static int atif_ioctl(int cmd, void *arg) { static char aarp_mcast[6] = {0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF}; struct ifreq atreq; @@ -1855,7 +1855,15 @@ case SIOCDIFADDR: case SIOCSARP: /* proxy AARP */ case SIOCDARP: /* proxy AARP */ - return atif_ioctl(cmd, (void *)arg); + { + int ret; + + rtnl_lock(); + ret = atif_ioctl(cmd, (void *)arg); + rtnl_unlock(); + + return ret; + } /* Physical layer ioctl calls */ case SIOCSIFLINK: case SIOCGIFHWADDR: diff -u --recursive --new-file v2.4.9/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.4.9/linux/net/ipv4/icmp.c Sun Aug 12 13:28:01 2001 +++ linux/net/ipv4/icmp.c Tue Aug 28 07:09:44 2001 @@ -3,7 +3,7 @@ * * Alan Cox, * - * Version: $Id: icmp.c,v 1.79 2001/08/03 22:20:39 davem Exp $ + * Version: $Id: icmp.c,v 1.80 2001/08/22 20:38:41 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -16,6 +16,9 @@ * Other than that this module is a complete rewrite. * * Fixes: + * Clemens Fruhwirth : introduce global icmp rate limiting + * with icmp type masking ability instead + * of broken per type icmp timeouts. * Mike Shaver : RFC1122 checks. * Alan Cox : Multicast ping reply as self. * Alan Cox : Fix atomicity lockup in ip_build_xmit @@ -143,6 +146,21 @@ /* Control parameter - ignore bogus broadcast responses? */ int sysctl_icmp_ignore_bogus_error_responses; +/* + * Configurable global rate limit. + * + * ratelimit defines tokens/packet consumed for dst->rate_token bucket + * ratemask defines which icmp types are ratelimited by setting + * it's bit position. + * + * default: + * dest unreachable (0x03), source quench (0x04), + * time exceeded (0x11), parameter problem (0x12) + */ + +int sysctl_icmp_ratelimit = 1*HZ; +int sysctl_icmp_ratemask = 0x1818; + /* * ICMP control array. This specifies what to do with each ICMP. */ @@ -153,7 +171,6 @@ unsigned long *input; /* Address to increment on input */ void (*handler)(struct sk_buff *skb); short error; /* This ICMP is classed as an error message */ - int *timeout; /* Rate limit */ }; static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; @@ -221,11 +238,6 @@ * Note that the same dst_entry fields are modified by functions in * route.c too, but these work for packet destinations while xrlim_allow * works for icmp destinations. This means the rate limiting information - * for one "ip object" is shared. - * - * Note that the same dst_entry fields are modified by functions in - * route.c too, but these work for packet destinations while xrlim_allow - * works for icmp destinations. This means the rate limiting information * for one "ip object" is shared - and these ICMPs are twice limited: * by source and by destination. * @@ -238,15 +250,12 @@ int xrlim_allow(struct dst_entry *dst, int timeout) { unsigned long now; - static int burst = HZ; now = jiffies; dst->rate_tokens += now - dst->rate_last; dst->rate_last = now; - if (burst < XRLIM_BURST_FACTOR*timeout) - burst = XRLIM_BURST_FACTOR*timeout; - if (dst->rate_tokens > burst) - dst->rate_tokens = burst; + if (dst->rate_tokens > XRLIM_BURST_FACTOR*timeout) + dst->rate_tokens = XRLIM_BURST_FACTOR*timeout; if (dst->rate_tokens >= timeout) { dst->rate_tokens -= timeout; return 1; @@ -258,22 +267,22 @@ { struct dst_entry *dst = &rt->u.dst; - if (type > NR_ICMP_TYPES || !icmp_pointers[type].timeout) + if (type > NR_ICMP_TYPES) return 1; /* Don't limit PMTU discovery. */ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) return 1; - /* Redirect has its own rate limit mechanism */ - if (type == ICMP_REDIRECT) - return 1; - /* No rate limit on loopback */ if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) return 1; - return xrlim_allow(dst, *(icmp_pointers[type].timeout)); + /* Limit if icmp type is enabled in ratemask. */ + if((1 << type) & sysctl_icmp_ratemask) + return xrlim_allow(dst, sysctl_icmp_ratelimit); + else + return 1; } /* @@ -929,57 +938,43 @@ goto drop; } - -/* - * Configurable rate limits. - * Someone should check if these default values are correct. - * Note that these values interact with the routing cache GC timeout. - * If you chose them too high they won't take effect, because the - * dst_entry gets expired too early. The same should happen when - * the cache grows too big. - */ -int sysctl_icmp_destunreach_time = 1*HZ; -int sysctl_icmp_timeexceed_time = 1*HZ; -int sysctl_icmp_paramprob_time = 1*HZ; -int sysctl_icmp_echoreply_time; /* don't limit it per default. */ - /* * This table is the definition of how we handle ICMP. */ static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1] = { /* ECHO REPLY (0) */ - { &icmp_statistics[0].IcmpOutEchoReps, &icmp_statistics[0].IcmpInEchoReps, icmp_discard, 0, &sysctl_icmp_echoreply_time}, - { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, - { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].IcmpOutEchoReps, &icmp_statistics[0].IcmpInEchoReps, icmp_discard, 0 }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 }, /* DEST UNREACH (3) */ - { &icmp_statistics[0].IcmpOutDestUnreachs, &icmp_statistics[0].IcmpInDestUnreachs, icmp_unreach, 1, &sysctl_icmp_destunreach_time }, + { &icmp_statistics[0].IcmpOutDestUnreachs, &icmp_statistics[0].IcmpInDestUnreachs, icmp_unreach, 1 }, /* SOURCE QUENCH (4) */ - { &icmp_statistics[0].IcmpOutSrcQuenchs, &icmp_statistics[0].IcmpInSrcQuenchs, icmp_unreach, 1, }, + { &icmp_statistics[0].IcmpOutSrcQuenchs, &icmp_statistics[0].IcmpInSrcQuenchs, icmp_unreach, 1 }, /* REDIRECT (5) */ - { &icmp_statistics[0].IcmpOutRedirects, &icmp_statistics[0].IcmpInRedirects, icmp_redirect, 1, }, - { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, - { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].IcmpOutRedirects, &icmp_statistics[0].IcmpInRedirects, icmp_redirect, 1 }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 }, /* ECHO (8) */ - { &icmp_statistics[0].IcmpOutEchos, &icmp_statistics[0].IcmpInEchos, icmp_echo, 0, }, - { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, - { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, }, + { &icmp_statistics[0].IcmpOutEchos, &icmp_statistics[0].IcmpInEchos, icmp_echo, 0 }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1 }, /* TIME EXCEEDED (11) */ - { &icmp_statistics[0].IcmpOutTimeExcds, &icmp_statistics[0].IcmpInTimeExcds, icmp_unreach, 1, &sysctl_icmp_timeexceed_time }, + { &icmp_statistics[0].IcmpOutTimeExcds, &icmp_statistics[0].IcmpInTimeExcds, icmp_unreach, 1 }, /* PARAMETER PROBLEM (12) */ - { &icmp_statistics[0].IcmpOutParmProbs, &icmp_statistics[0].IcmpInParmProbs, icmp_unreach, 1, &sysctl_icmp_paramprob_time }, + { &icmp_statistics[0].IcmpOutParmProbs, &icmp_statistics[0].IcmpInParmProbs, icmp_unreach, 1 }, /* TIMESTAMP (13) */ - { &icmp_statistics[0].IcmpOutTimestamps, &icmp_statistics[0].IcmpInTimestamps, icmp_timestamp, 0, }, + { &icmp_statistics[0].IcmpOutTimestamps, &icmp_statistics[0].IcmpInTimestamps, icmp_timestamp, 0 }, /* TIMESTAMP REPLY (14) */ - { &icmp_statistics[0].IcmpOutTimestampReps, &icmp_statistics[0].IcmpInTimestampReps, icmp_discard, 0, }, + { &icmp_statistics[0].IcmpOutTimestampReps, &icmp_statistics[0].IcmpInTimestampReps, icmp_discard, 0 }, /* INFO (15) */ - { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_discard, 0, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_discard, 0 }, /* INFO REPLY (16) */ - { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_discard, 0, }, + { &icmp_statistics[0].dummy, &icmp_statistics[0].dummy, icmp_discard, 0 }, /* ADDR MASK (17) */ - { &icmp_statistics[0].IcmpOutAddrMasks, &icmp_statistics[0].IcmpInAddrMasks, icmp_address, 0, }, + { &icmp_statistics[0].IcmpOutAddrMasks, &icmp_statistics[0].IcmpInAddrMasks, icmp_address, 0 }, /* ADDR MASK REPLY (18) */ - { &icmp_statistics[0].IcmpOutAddrMaskReps, &icmp_statistics[0].IcmpInAddrMaskReps, icmp_address_reply, 0, } + { &icmp_statistics[0].IcmpOutAddrMaskReps, &icmp_statistics[0].IcmpInAddrMaskReps, icmp_address_reply, 0 } }; void __init icmp_init(struct net_proto_family *ops) diff -u --recursive --new-file v2.4.9/linux/net/ipv4/netfilter/ip_nat_helper.c linux/net/ipv4/netfilter/ip_nat_helper.c --- v2.4.9/linux/net/ipv4/netfilter/ip_nat_helper.c Fri Apr 27 14:15:01 2001 +++ linux/net/ipv4/netfilter/ip_nat_helper.c Tue Aug 28 07:09:44 2001 @@ -267,8 +267,8 @@ /* Replace with NOPs. */ tcph->check = ip_nat_cheat_check(*((u_int16_t *)(opt + i))^0xFFFF, - 0, tcph->check); - opt[i] = opt[i+1] = 0; + (TCPOPT_NOP<<8)|TCPOPT_NOP, tcph->check); + opt[i] = opt[i+1] = TCPOPT_NOP; } else DEBUGP("Something wrong with SACK_PERM.\n"); } diff -u --recursive --new-file v2.4.9/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- v2.4.9/linux/net/ipv4/sysctl_net_ipv4.c Sun Mar 25 18:14:25 2001 +++ linux/net/ipv4/sysctl_net_ipv4.c Tue Aug 28 07:09:44 2001 @@ -1,7 +1,7 @@ /* * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem. * - * $Id: sysctl_net_ipv4.c,v 1.48 2001/02/23 01:39:05 davem Exp $ + * $Id: sysctl_net_ipv4.c,v 1.49 2001/08/22 20:38:41 davem Exp $ * * Begun April 1, 1996, Mike Shaver. * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] @@ -32,10 +32,8 @@ extern int sysctl_ip_dynaddr; /* From icmp.c */ -extern int sysctl_icmp_destunreach_time; -extern int sysctl_icmp_timeexceed_time; -extern int sysctl_icmp_paramprob_time; -extern int sysctl_icmp_echoreply_time; +extern int sysctl_icmp_ratelimit; +extern int sysctl_icmp_ratemask; /* From igmp.c */ extern int sysctl_igmp_max_memberships; @@ -178,14 +176,6 @@ {NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses", &sysctl_icmp_ignore_bogus_error_responses, sizeof(int), 0644, NULL, &proc_dointvec}, - {NET_IPV4_ICMP_DESTUNREACH_RATE, "icmp_destunreach_rate", - &sysctl_icmp_destunreach_time, sizeof(int), 0644, NULL, &proc_dointvec}, - {NET_IPV4_ICMP_TIMEEXCEED_RATE, "icmp_timeexceed_rate", - &sysctl_icmp_timeexceed_time, sizeof(int), 0644, NULL, &proc_dointvec}, - {NET_IPV4_ICMP_PARAMPROB_RATE, "icmp_paramprob_rate", - &sysctl_icmp_paramprob_time, sizeof(int), 0644, NULL, &proc_dointvec}, - {NET_IPV4_ICMP_ECHOREPLY_RATE, "icmp_echoreply_rate", - &sysctl_icmp_echoreply_time, sizeof(int), 0644, NULL, &proc_dointvec}, {NET_IPV4_ROUTE, "route", NULL, 0, 0555, ipv4_route_table}, #ifdef CONFIG_IP_MULTICAST {NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships", @@ -227,6 +217,10 @@ &sysctl_tcp_app_win, sizeof(int), 0644, NULL, &proc_dointvec}, {NET_TCP_ADV_WIN_SCALE, "tcp_adv_win_scale", &sysctl_tcp_adv_win_scale, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV4_ICMP_RATELIMIT, "icmp_ratelimit", + &sysctl_icmp_ratelimit, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV4_ICMP_RATEMASK, "icmp_ratemask", + &sysctl_icmp_ratemask, sizeof(int), 0644, NULL, &proc_dointvec}, {0} }; diff -u --recursive --new-file v2.4.9/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.4.9/linux/net/ipv4/tcp.c Mon Aug 27 12:41:49 2001 +++ linux/net/ipv4/tcp.c Tue Aug 28 07:11:33 2001 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.208 2001/08/13 18:56:12 davem Exp $ + * Version: $Id: tcp.c,v 1.209 2001/08/28 00:31:04 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -2361,7 +2361,7 @@ val = (val ? : sysctl_tcp_fin_timeout)/HZ; break; case TCP_DEFER_ACCEPT: - val = tp->defer_accept == 0 ? 0 : (TCP_TIMEOUT_INIT<<(tp->defer_accept-1)); + val = tp->defer_accept == 0 ? 0 : ((TCP_TIMEOUT_INIT/HZ)<<(tp->defer_accept-1)); break; case TCP_WINDOW_CLAMP: val = tp->window_clamp; diff -u --recursive --new-file v2.4.9/linux/net/socket.c linux/net/socket.c --- v2.4.9/linux/net/socket.c Wed Jul 25 17:10:27 2001 +++ linux/net/socket.c Tue Aug 28 10:56:06 2001 @@ -303,8 +303,7 @@ } static struct vfsmount *sock_mnt; -static DECLARE_FSTYPE(sock_fs_type, "sockfs", sockfs_read_super, - FS_NOMOUNT|FS_SINGLE); +static DECLARE_FSTYPE(sock_fs_type, "sockfs", sockfs_read_super, FS_NOMOUNT); static int sockfs_delete_dentry(struct dentry *dentry) { return 1; @@ -1205,13 +1204,14 @@ msg.msg_iovlen=1; msg.msg_control=NULL; msg.msg_controllen=0; - msg.msg_namelen=addr_len; + msg.msg_namelen=0; if(addr) { err = move_addr_to_kernel(addr, addr_len, address); if (err < 0) goto out_put; msg.msg_name=address; + msg.msg_namelen=addr_len; } if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT;