From 4bc4a88c4c9b22e40b687c14704b1e3e138f16cf Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:17:38 -0500 Subject: [PATCH] pre-2.1.132-4.. There's a new pre-patch on ftp.kernel.org. I've been waiting for a few other things, but the pre-patches are getting to be so big that it's getting unwieldly, so I'll probably make a real 2.1.132 real soon now. In the meantime, there's a pre-patch that people can verify for sanity (this one should have coda-fs back to working order, for example - patch craziness corrupted a simple update in pre-3). Linus --- Documentation/Configure.help | 13 +- Documentation/fb/matroxfb.txt | 283 + arch/i386/kernel/smp.c | 1 - arch/ppc/8xx_io/enet.c | 8 +- arch/ppc/Makefile | 2 - arch/ppc/amiga/bootinfo.c | 4 +- arch/ppc/amiga/config.c | 2 +- arch/ppc/boot/Makefile | 3 + arch/ppc/boot/misc.c | 36 +- arch/ppc/coffboot/Makefile | 12 - arch/ppc/common_defconfig | 20 +- arch/ppc/config.in | 3 - arch/ppc/defconfig | 1 - arch/ppc/kernel/Makefile | 9 +- arch/ppc/kernel/apus_setup.c | 4 +- arch/ppc/kernel/head.S | 66 +- arch/ppc/kernel/irq.c | 33 +- arch/ppc/kernel/mbx_setup.c | 15 +- arch/ppc/kernel/misc.S | 175 +- arch/ppc/kernel/pci.c | 32 +- arch/ppc/kernel/ppc_htab.c | 3 +- arch/ppc/kernel/ppc_ksyms.c | 2 + arch/ppc/kernel/prep_pci.c | 20 +- arch/ppc/kernel/prep_setup.c | 5 - arch/ppc/kernel/process.c | 4 + arch/ppc/kernel/setup.c | 19 +- arch/ppc/kernel/smp.c | 26 +- arch/ppc/kernel/time.c | 22 +- arch/ppc/lib/Makefile | 2 +- arch/ppc/mbx_defconfig | 89 +- arch/ppc/mm/init.c | 128 +- arch/ppc/pmac_defconfig | 1 - arch/ppc/prep_defconfig | 1 - drivers/macintosh/mediabay.c | 8 +- drivers/macintosh/via-pmu.c | 14 +- drivers/video/Config.in | 10 +- drivers/video/atyfb.c | 20 +- drivers/video/cgsixfb.c | 14 +- drivers/video/chipsfb.c | 2 + drivers/video/controlfb.c | 517 +- drivers/video/controlfb.h | 46 +- drivers/video/creatorfb.c | 55 +- drivers/video/cyberfb.c | 34 +- drivers/video/cyberfb.h | 2 +- drivers/video/fbcon-cfb8.c | 16 +- drivers/video/fbcon.c | 199 +- drivers/video/font_sun12x22.c | 11268 ++++++++++++++++---------------- drivers/video/imsttfb.c | 662 +- drivers/video/macfb.c | 165 +- drivers/video/matroxfb.c | 1354 ++-- drivers/video/offb.c | 76 +- drivers/video/retz3fb.c | 54 +- drivers/video/sbusfb.c | 6 +- drivers/video/tgafb.c | 52 +- drivers/video/virgefb.c | 1 + fs/buffer.c | 14 +- fs/dcache.c | 12 +- fs/ext2/file.c | 4 - include/asm-ppc/amigappc.h | 8 +- include/asm-ppc/io.h | 8 +- include/asm-ppc/mmu_context.h | 6 +- include/asm-ppc/resource.h | 2 +- include/asm-ppc/termios.h | 2 - include/linux/coda.h | 547 +- include/linux/coda_linux.h | 4 +- include/linux/coda_psdev.h | 9 +- include/linux/fb.h | 2 + include/linux/fs.h | 22 +- include/video/fbcon.h | 10 + mm/filemap.c | 120 +- mm/vmscan.c | 4 +- 71 files changed, 9111 insertions(+), 7282 deletions(-) create mode 100644 Documentation/fb/matroxfb.txt diff --git a/Documentation/Configure.help b/Documentation/Configure.help index a1aabb540872..26639326c90c 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -1767,7 +1767,7 @@ CONFIG_FB_MATROX Matrox Millennium support CONFIG_FB_MATROX_MILLENIUM - Say Y here if you have Matrox Millennium or Matrox Milleninium II in + Say Y here if you have Matrox Millennium or Matrox Millennium II in the box. If you select "Advanced lowlevel driver options", you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can also use font @@ -1783,13 +1783,10 @@ CONFIG_FB_MATROX_MYSTIQUE Matrox G100 support CONFIG_FB_MATROX_G100 - Say Y here if you have Matrox Productiva G100 in the box. But THIS - DRIVER IS NOT TESTED BECAUSE OF I HAVE NO G100 board and G100 - technical sheets are top secret at this time. But driver should not - cause any damage to your computer. - If you select "Advanced lowlevel driver options", you should check - 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and - 32 bpp packed pixel. You can also use font widths different from 8. + Say Y here if you have Matrox Productiva G100 in the box. If you + select "Advanced lowlevel driver options", you should check 8 bpp + packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and 32 bpp + packed pixel. You can also use font widths different from 8. Matrox unified driver multihead support CONFIG_FB_MATROX_MULTIHEAD diff --git a/Documentation/fb/matroxfb.txt b/Documentation/fb/matroxfb.txt new file mode 100644 index 000000000000..cb1b9b2091ac --- /dev/null +++ b/Documentation/fb/matroxfb.txt @@ -0,0 +1,283 @@ +[This file is cloned from VesaFB. Thanks go to Gerd Knorr] + +what is matroxfb? +================= + +This is a driver for a graphic framebuffer for Matrox devices on +Alpha, Intel and PPC boxes. + +Advantages: + + * It provides a nice large console (128 cols + 48 lines with 1024x768) + without using tiny, unreadable fonts. + * You can run XF68_FBDev on top of /dev/fb0 + * Most important: boot logo :-) + +Disadvantages: + + * graphic mode is slower than text mode... but you should not notice + if you use same resolution as you used in textmode. + + +How to use it? +============== + +Switching modes is done using the video=matrox:vesa=... boot parameter +or using `fbset' program. + +You should compile in both vgacon (to boot if you remove you Matrox from +box) and matroxfb (for graphics mode). You should not compile-in vesafb +unless you have primary display on non-Matrox VBE2.0 device (see +Documentation/vesafb.txt for details). + +Currently supported video modes are (through vesa=... interface, PowerMac +has (as addon) compatibility code. + +bpp | 640x400 640x480 768x576 800x600 960x720 1024x768 1152x864 1280x1024 1408x1056 1600x1200 +----+---------------------------------------------------------------------------------------------- + 4 | 0x12 0x102 0x104 0x106 + 8 | 0x100 0x101 0x180 0x103 0x188 0x105 0x190 0x107 0x198 0x11C + 15 | 0x110 0x181 0x113 0x189 0x116 0x191 0x119 0x199 0x11D + 16 | 0x111 0x182 0x114 0x18A 0x117 0x192 0x11A 0x19A 0x11E + 24 | 0x1B2 0x184 0x1B5 0x18C 0x1B8 0x194 0x1BB 0x19C 0x1BF + 32 | 0x112 0x183 0x115 0x18B 0x118 0x193 0x11B 0x19B + +text | 640x400 640x480 1056x344 1056x400 1056x480 +-----+------------------------------------------------ + 8x8 | 0x1C0 0x108 0x10A 0x10B 0x10C +8x16 | 2, 3, 7 0x109 + +You can enter these number either hexadecimal (leading `0x') or decimal (0x100 = 256). You can also +use value + 512 to achieve compatibility with your old number passed to vesafb. + +Non-listed number can be achieved by more complicated command-line, for example +1600x1200x32bpp can be specified by `video=matrox:vesa:0x11C,depth:32'. + + +X11 +=== + +XF68_FBDev should work just fine, but it is non-accelerated. On non-intel +architectures there are some glitches for 24bpp videomodes. 8, 16 and 32bpp +works fine. + +Running another (accelerated) X-Server like XF86_SVGA works too. But (at least) +XFree servers have big troubles in multihead configurations (even on first +head, not even talking about second). + + +SVGALib +======= + +Driver contains SVGALib compatibility code. It is turned on by choosing textual +mode for console. You can do it at boottime by using videomode 2,3,7,0x108-0x10C +or 0x1C0. At runtime, `fbset -depth 0' does this work. +Unfortunately, after SVGALib application exits, screen contents is corrupted. +Switching to another console and back fixes it. I hope that it is SVGALib and +not mine problem, but I'm not sure. + + +Configuration +============= + +You can pass kernel command line options to vesafb with +`video=matrox:option1,option2:value2,option3' (multiple options should be +separated by comma, values are separated from options by `:'). +Accepted options: + +mem:X - size of memory (X can be in megabytes, kilobytes or bytes) + You can only decrease value determined by driver because of + it always probe for memory. Default is to use whole detected + memory usable for on-screen display (i.e. max. 8MB). +disabled - do not load driver; you can use also `off', but `disabled' + is here too. +enabled - load driver, if you have `video=matrox:disabled' in LILO configuration, + you can override it by this (you cannot override `off'). + It is default. +noaccel - do not use acceleration engine. It does not work on Alphas. +accel - use acceleration engine. It is default. +nopan - create initial consoles with vyres = yres, thus disabling virtual + scrolling. +pan - create initial consoles as tall as possible (vyres = memory/vxres). + It is default. +nopciretry - disable PCI retries. It is needed for some broken chipsets, + it is autodetected for intel's 82437. In this case device does + not comply to PCI 2.1 specs (it will not guarantee that every transaction + terminate with success or retry in 32 PCLK). +pciretry - enable PCI retries. It is default, except for intel's 82437. +novga - disables VGA I/O ports. It is default if BIOS did not enable device. + You should not use this option, some boards then do not restart without + power off. +vga - preserve state of VGA I/O ports. It is default. Driver does not enable + VGA I/O if BIOS did not it (it is not safe to enable it in most cases). +nobios - disables BIOS ROM. It is default if BIOS did not enable BIOS itself. + You should not use this option, some boards then do not restart without + power off. +bios - preserve state of BIOS ROM. It is default. Driver does not enable BIOS + if BIOS was not enabled before. +noinit - tells driver, that devices were already initialized. You should use it + if you have G100 and/or if driver cannot detect memory, you see strange + pattern on screen and so on. Devices not enabled by BIOS are still + initialized. +init - driver initializes every device it knows about. It is default. +inv24 - change timings parameters for 24bpp modes on Millenium and Millenium II. + Specify this if you see strange color shadows around characters. +noinv24 - use standard timmings. It is default. +inverse - invert colors on screen (for LCD displays) +noinverse - show true colors on screen. It is default. +dev:X - bind driver to device X. Driver numbers device from 0 up to N, where device + 0 is first `known' device found, 1 second and so on. lspci lists + devices in this order. + Default is `every' known device for driver with multihead support and + first working device (usually dev:0) for driver without multihead support. +nohwcursor - disables hardware cursor (use software cursor instead). +hwcursor - enables hardware cursor. It is default. If you are using non-accelerated mode + (`noaccel' or `fbset -accel false'), software cursor is used (except for + text mode). +noblink - disables cursor blinking. Cursor in text mode always blinks (hw limitation). +blink - enables cursor blinking. It is default. +nofastfont - disables fastfont feature. It is default. +fastfont:X - enables fastfont feature. X specifies size of memory reserved for font data, + it must be >= (fontwidth*fontheight*chars_in_font)/8. It is faster on + Gx00 series, but slower on older cards. +grayscale - enable grayscale summing. It works in PSEUDOCOLOR modes (text, 4bpp, 8bpp). In + DIRECTCOLOR modes it is limited to characters displayed through putc/putcs. Direct + accesses to framebuffer can paint colors. +nograyscale - disable grayscale summing. It is default. +cross4MB - enables that pixel line can cross 4MB boundary. It is default for non-Millenium. +nocross4MB - pixel line must not cross 4MB boundary. It is default for Millenium I or II, + because of these devices have hardware limitations which do not allow this. + But this option is incompatible with some (if not all yet released) versions + of XF86_FBDev. +vesa:X - selects startup videomode. X is number from 0 to 0x1FF, see table above + for detailed explanation. Default is 640x480, 8bpp if driver has 8bpp support. + Otherwise first available of 640x350x4bpp, 640x480x15bpp, 640x480x24bpp, + 640x480x32bpp or 80x25 text (80x25 text is always available). +If you are not satisfied with videomode selected by `vesa' option, you +can modify it with these options: +xres:X - horizontal resolution, in pixels. Default is derived from `vesa' option. +yres:X - vertical resolution, in pixel lines. Default is derived from `vesa' option. +upper:X - top boundary: lines between end of VSYNC pulse and start of first pixel line + of picture. Default is derived from `vesa' option. +lower:X - bottom boundary: lines between end of picture and start of VSYNC pulse. + Default is derived from `vesa' option. +vslen:X - length of VSYNC pulse, in lines. Default is derived from `vesa' option. +left:X - left boundary: pixels between end of HSYNC pulse and first pixel. Default + is derived from `vesa' option. +right:X - right boundary: pixels between end of picture and start of HSYNC pulse. + Default is derived from `vesa' option. +hslen:X - length of HSYNC pulse, in pixels. Default is derived from `vesa' option. +pixclock:X - dotclocks, in ps (picoseconds). Default is derived from `vesa' option and + from `fh' and `fv' options. +sync:X - sync. pulse - bit 0 inverts HSYNC polarity, bit 1 VSYNC polarity. + If bit 3 (value 0x08) is set, composite sync instead of HSYNC is generated. + If bit 5 (value 0x20) is set, sync on green is turned on. + Default depends on `vesa'. +depth:X - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on `vesa'. +If you know capabilities of your monitor, you can specify some (or all) of `pixclk', `fh' +and `fv'. In this case, `pixclock' is computed so that pixclock <= maxclk, real_fh <= fh +and real_fv <= fv. +maxclk:X - maximum dotclock. X can be specified in MHz, kHz or Hz. Default is `don't care'. +fh:X - maximum horizontal synchronization frequency. X can be specified in kHz or Hz. + Default is `don't care'. +fv:X - maximum vertical frequency. X must be specified in Hz. Default is 70 for modes + derived from `vesa' with yres <= 400, 60Hz for yres > 400. + + +Limitations +=========== + +There are known and unknown bugs, features and misfeatures. +Currently there are following known bugs: + + G100 support does not work as expected, I'm still investigating this one. + Using `noinit' option works, but only for `first' head :-( + + SVGALib does not restore screen on exit + + generic fbcon-cfbX procedures do not work on Alphas. Due to this, + `noaccel' (and cfb4 accel) driver does not work on Alpha. So everyone + with access to /dev/fb* on Alpha can hang machine (you should restrict + access to /dev/fb* - everyone with access to this device can destroy + your monitor, believe me...). + + 24bpp does not support correctly XF-FBDev on big-endian architectures. + + interlaced text mode is not supported; it looks like hardware limitiation, + but I'm not sure. + + maybe more... +And following misfeatures: + + SVGALib does not restore screen on exit. + + pixclock for text modes is limited by hardware to + 83MHz on G200 + 66MHz on Millenium I + 60MHz on Millenium II + Because of I have not access to other devices, I do not know specific + frequencies for them. So driver does not check this and allows you to + set frequency higher that this. It cause sparks, black holes and other + pretty effects on screen. Device was not destroyed during tests :-) + + my Millenium G200 oscillator has frequency range from 35MHz to 380MHz + (and it works with 8bpp on about 320MHz dotclocks (and changed mclk)). + But Matrox says on product sheet that VCO limit is 50-250MHz, so I believe + them (maybe that chip overheates, but it has very big cooler (G100 has + not one), so it should work). + + special mixed video/graphics videomodes of Mystique and Gx00 - 2G8V16 and + G16V16 are not supported + + color keying is not supported + + feature connector of Mystique and Gx00 is set to VGA mode (it is disabled + by BIOS) + + DCC (monitor detection) protocol is not implemented + + some check for input values are not so strict how it should be (you can + specify vslen=4000 and so on). + + maybe more... +And following features: + + 4bpp is available only on Millenium I and Millenium II. It is hardware + limitiation. + + current fbset is not able to set 15bpp videomode: you must specify + depth==16 and green.length==5. fbset does not allow you to set + green.length. + + hardware cursor is available only in accelerated videomodes. Maybe that + this is misfeature and not feature. + + text mode uses 6 bit VGA palette instead of 8 bit (one of 262144 colors + instead of one of 16M colors). It is due to hardware limitation of + MilleniumI/II and SVGALib compatibility. + + +Benchmarks +========== +It is time to redraw whole screen 1000 times in 1024x768, 60Hz. It is +time for draw 6144000 characters on screen through /dev/vcsa +(for 32bpp it is about 3GB of data (exactly 3000 MB); for 8x16 font in +16 seconds, i.e. 187MBps). +Times were obtained from one older version of driver, now they are about 3% +faster, it is kernel-space only time on P-II/350MHz, Millenium I in 33MHz +PCI slot, G200 in AGP 2x slot. I did not test vgacon. + +NOACCEL + 8x16 12x22 + MilleniumI G200 MilleniumI G200 +8bpp 16.42 9.54 12.33 9.13 +16bpp 21.00 15.70 19.11 15.02 +24bpp 36.66 36.66 35.00 35.00 +32bpp 35.00 30.00 33.85 28.66 + +ACCEL, nofastfont + 8x16 12x22 6x11 + MilleniumI G200 MilleniumI G200 MilleniumI G200 +8bpp 7.79 7.24 13.55 7.78 30.00 21.01 +16bpp 9.13 7.78 16.16 7.78 30.00 21.01 +24bpp 14.17 10.72 18.69 10.24 34.99 21.01 +32bpp 16.15 16.16 18.73 13.09 34.99 21.01 + +ACCEL, fastfont + 8x16 12x22 6x11 + MilleniumI G200 MilleniumI G200 MilleniumI G200 +8bpp 8.41 6.01 6.54 4.37 16.00 10.51 +16bpp 9.54 9.12 8.76 6.17 17.52 14.01 +24bpp 15.00 12.36 11.67 10.00 22.01 18.32 +32bpp 16.18 18.29* 12.71 12.74 24.44 21.00 + +TEXT + 8x16 + MilleniumI G200 +TEXT 3.29 1.50 + + +* Yes, it is slower than Millenium I. +-- +Petr Vandrovec diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 60979b172a59..c01eb35f5b73 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -1175,7 +1175,6 @@ void __init smp_boot_cpus(void) smp_done: } - void send_IPI(int dest, int vector) { unsigned long cfg; diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c index 8c3401d6fefe..126b724be2e6 100644 --- a/arch/ppc/8xx_io/enet.c +++ b/arch/ppc/8xx_io/enet.c @@ -1,4 +1,5 @@ /* + * $Id: enet.c,v 1.8 1998/11/15 19:58:07 cort Exp $ * Ethernet driver for Motorola MPC8xx. * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) * @@ -657,7 +658,7 @@ __initfunc(int cpm_enet_init(void)) cp = cpmp; /* Get pointer to Communication Processor */ - immap = (immap_t *)MBX_IMAP_ADDR; /* and to internal registers */ + immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ /* Allocate some private information. */ @@ -719,11 +720,11 @@ __initfunc(int cpm_enet_init(void)) * These are relative offsets in the DP ram address space. * Initialize base addresses for the buffer descriptors. */ - i = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE); + i = m8xx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE); ep->sen_genscc.scc_rbase = i; cep->rx_bd_base = (cbd_t *)&cp->cp_dpmem[i]; - i = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE); + i = m8xx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE); ep->sen_genscc.scc_tbase = i; cep->tx_bd_base = (cbd_t *)&cp->cp_dpmem[i]; @@ -912,4 +913,3 @@ __initfunc(int cpm_enet_init(void)) return 0; } - diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index cd98b4513dc6..990b24b84062 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -16,8 +16,6 @@ KERNELLOAD =0xc0000000 ifeq ($(shell uname -m),ppc) CHECKS = checks -else -CROSS_COMPILE = ppc-linux-elf- endif ASFLAGS = diff --git a/arch/ppc/amiga/bootinfo.c b/arch/ppc/amiga/bootinfo.c index f24a0c5b853c..7639de68e594 100644 --- a/arch/ppc/amiga/bootinfo.c +++ b/arch/ppc/amiga/bootinfo.c @@ -17,8 +17,8 @@ extern char cmd_line[CL_SIZE]; int num_memory = 0; -extern struct mem_info memory[NUM_MEMINFO]; -extern struct mem_info ramdisk; +struct mem_info memory[NUM_MEMINFO]; +struct mem_info ramdisk; extern int amiga_parse_bootinfo(const struct bi_record *); extern int atari_parse_bootinfo(const struct bi_record *); diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index f79172390af9..2335adfb97c8 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -742,7 +742,7 @@ static void amiga_savekmsg_init(void) static void amiga_serial_putc(char c) { custom.serdat = (unsigned char)c | 0x100; - iobarrier (); + iobarrier_rw (); while (!(custom.serdatr & 0x2000)) ; } diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index fde1ad4c6e34..da4945fd7251 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -48,6 +48,9 @@ OBJECTS += mbxtty.o CFLAGS += -DCONFIG_MBX else OBJECTS += vreset.o kbd.o + ifeq ($(CONFIG_SERIAL_CONSOLE),y) + OBJECTS += ns16550.o + endif endif all: zImage diff --git a/arch/ppc/boot/misc.c b/arch/ppc/boot/misc.c index 42cb533dafe8..470e1e4a98fa 100644 --- a/arch/ppc/boot/misc.c +++ b/arch/ppc/boot/misc.c @@ -1,7 +1,7 @@ /* * misc.c * - * $Id: misc.c,v 1.52 1998/09/19 01:21:24 cort Exp $ + * $Id: misc.c,v 1.53 1998/12/15 17:40:15 cort Exp $ * * Adapted for PowerPC by Gary Thomas * @@ -12,7 +12,7 @@ #include #include "../coffboot/zlib.h" #include "asm/residual.h" -#include +#include #include #include #include @@ -23,6 +23,10 @@ #ifdef CONFIG_FADS #include #endif +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX) +#include "ns16550.h" +struct NS16550 *com_port; +#endif /* CONFIG_SERIAL_CONSOLE */ /* * Please send me load/board info and such data for hardware not @@ -42,6 +46,7 @@ char *end_avail; * save here and pass to the kernel (command line and board info). * On the MBX we grab some known memory holes to hold this information. */ +char cmd_preset[] = "console=tty0 console=ttyS0,9600n8"; char cmd_buf[256]; char *cmd_line = cmd_buf; @@ -108,12 +113,19 @@ static void scroll() tstc(void) { +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX) + return (CRT_tstc() || NS16550_tstc(com_port)); +#else return (CRT_tstc() ); +#endif /* CONFIG_SERIAL_CONSOLE */ } getc(void) { while (1) { +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX) + if (NS16550_tstc(com_port)) return (NS16550_getc(com_port)); +#endif /* CONFIG_SERIAL_CONSOLE */ if (CRT_tstc()) return (CRT_getc()); } } @@ -123,6 +135,11 @@ putc(const char c) { int x,y; +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX) + NS16550_putc(com_port, c); + if ( c == '\n' ) NS16550_putc(com_port, '\r'); +#endif /* CONFIG_SERIAL_CONSOLE */ + x = orig_x; y = orig_y; @@ -162,12 +179,21 @@ void puts(const char *s) y = orig_y; while ( ( c = *s++ ) != '\0' ) { +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX) + NS16550_putc(com_port, c); + if ( c == '\n' ) NS16550_putc(com_port, '\r'); +#endif /* CONFIG_SERIAL_CONSOLE */ + if ( c == '\n' ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } + } else if (c == '\b') { + if (x > 0) { + x--; + } } else { vidmem [ ( x + cols * y ) * 2 ] = c; if ( ++x >= cols ) { @@ -358,6 +384,10 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R _put_MSR(_get_MSR() & ~0x0030); vga_init(0xC0000000); +#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX) + com_port = (struct NS16550 *)NS16550_init(0); +#endif /* CONFIG_SERIAL_CONSOLE */ + if (residual) memcpy(hold_residual,residual,sizeof(RESIDUAL)); #else /* CONFIG_MBX */ @@ -510,6 +540,8 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R puts("\nLinux/PPC load: "); timer = 0; cp = cmd_line; + memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); + while ( *cp ) putc(*cp++); while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile index 72a6df4552d9..4669d22281e4 100644 --- a/arch/ppc/coffboot/Makefile +++ b/arch/ppc/coffboot/Makefile @@ -3,18 +3,6 @@ # # Paul Mackerras January 1997 -# PowerPC (cross) tools -ifneq ($(shell uname -m),ppc) -CROSS_COMPILE =powerpc-eabi- -endif - - -# PowerPC (cross) tools -ifneq ($(shell uname -m),ppc) -#CROSS_COMPILE =powerpc-eabi- -CROSS_COMPILE =ppc-linux-elf- -endif - HOSTCC = gcc HOSTCFLAGS = -O -I$(TOPDIR)/include diff --git a/arch/ppc/common_defconfig b/arch/ppc/common_defconfig index 916af99f149c..4a5ea33d918c 100644 --- a/arch/ppc/common_defconfig +++ b/arch/ppc/common_defconfig @@ -45,7 +45,7 @@ CONFIG_ADBMOUSE=y CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_PROC_DEVICETREE=y # CONFIG_KGDB is not set -CONFIG_XMON=y +# CONFIG_XMON is not set # CONFIG_TOTALMP is not set # CONFIG_BOOTX_TEXT is not set @@ -188,6 +188,7 @@ CONFIG_BMAC=y # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_RTL8139 is not set # CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y CONFIG_PCNET32=m @@ -239,10 +240,22 @@ CONFIG_SLIP=m # Console drivers # CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_OF is not set +CONFIG_FB_OF=y +# CONFIG_FB_CONTROL is not set +# CONFIG_FB_PLATINUM is not set +# CONFIG_FB_VALKYRIE is not set +CONFIG_FB_ATY=y +CONFIG_FB_IMSTT=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_S3TRIO is not set # CONFIG_FB_MATROX is not set +CONFIG_FB_ATY=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y # CONFIG_FBCON_FONTWIDTH8_ONLY is not set # CONFIG_FBCON_FONTS is not set CONFIG_FONT_8x8=y @@ -290,12 +303,13 @@ CONFIG_MSDOS_FS=m # CONFIG_VFAT_FS is not set CONFIG_PROC_FS=y CONFIG_NFS_FS=y -CONFIG_NFSD=y +CONFIG_NFSD=m # CONFIG_NFSD_SUN is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_CODA_FS is not set # CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_SYSV_FS is not set diff --git a/arch/ppc/config.in b/arch/ppc/config.in index 0378a8e4b97c..59223a45c462 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -22,9 +22,6 @@ choice 'Machine Type' \ if [ "$CONFIG_ALL_PPC" != "y" ];then define_bool CONFIG_MACH_SPECIFIC y fi - -bool 'Symmetric multi-processing support' CONFIG_SMP - endmenu if [ "$CONFIG_MBX" = "y" ];then diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index b0c9ad966f43..ae1303bb4813 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -14,7 +14,6 @@ CONFIG_PMAC=y # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set # CONFIG_MBX is not set -# CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index be0d214776b9..0914879f5607 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -15,8 +15,7 @@ OX_OBJS := ppc_ksyms.o setup.o O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \ - bitops.o ptrace.o align.o ppc_htab.o feature.o - + bitops.o ptrace.o align.o ppc_htab.o ifdef CONFIG_PCI O_OBJS += pci.o endif @@ -33,15 +32,17 @@ else ifeq ($(CONFIG_APUS),y) O_OBJS += apus_setup.o prom.o openpic.o else +ifneq ($(CONFIG_MBX),y) O_OBJS += prep_time.o pmac_time.o chrp_time.o \ pmac_setup.o pmac_support.o \ prep_pci.o pmac_pci.o chrp_pci.o \ - residual.o prom.o openpic.o + residual.o prom.o openpic.o feature.o OX_OBJS += chrp_setup.o prep_setup.o endif endif +endif -ifdef CONFIG_SMP +ifdef SMP O_OBJS += smp.o endif diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c index 93c2fe2d172e..c3a81ad3e836 100644 --- a/arch/ppc/kernel/apus_setup.c +++ b/arch/ppc/kernel/apus_setup.c @@ -329,9 +329,9 @@ unsigned long mm_ptov (unsigned long paddr) int i; for (i = 0; i < kmap_chunk_count;){ - unsigned long virt = kmap_chunks[i++]; - unsigned long size = kmap_chunks[i++]; 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; diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 4c528beb88dd..4374b30d5c41 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -1,7 +1,7 @@ /* * arch/ppc/kernel/head.S * - * $Id: head.S,v 1.111 1998/11/10 01:10:32 paulus Exp $ + * $Id: head.S,v 1.113 1998/12/02 18:41:00 cort Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -148,6 +148,10 @@ _start: * r4: virtual address of boot_infos_t * r5: 0 * + * APUS + * r3: 'APUS' + * Linux/m68k style BootInfo structure at &_end. + * * PREP * This is jumped to on prep systems right after the kernel is relocated * to its proper place in memory by the boot loader. The expected layout @@ -1204,9 +1208,23 @@ stack_ovf: Hash_base = 0x180000 Hash_bits = 12 /* e.g. 256kB hash table */ Hash_msk = (((1 << Hash_bits) - 1) * 64) - + + .globl hash_table_lock +hash_table_lock: +.long 0 + .globl hash_page hash_page: +#ifdef __SMP__ + lis r2,hash_table_lock@h + ori r2,r2,hash_table_lock@l + tophys(r2,r2,r6) +10: lwarx r6,0,r2 + stwcx. r2,0,r2 + bne- 10b + cmpi 0,0,r6,0 + bne 10b +#endif /* Get PTE (linux-style) and check access */ lwz r5,PG_TABLES(r5) tophys(r5,r5,r2) /* convert to phys addr */ @@ -1379,6 +1397,13 @@ found_slot: mtcrf 0xff,r3 mtlr r4 mtctr r5 +#ifdef __SMP__ + lis r2,hash_table_lock@h + ori r2,r2,hash_table_lock@l + tophys(r2,r2,r6) + li r6,0 + stw r6,0(r2) +#endif REST_GPR(0, r21) REST_2GPRS(1, r21) REST_4GPRS(3, r21) @@ -1392,6 +1417,13 @@ found_slot: rfi hash_page_out: +#ifdef __SMP__ + lis r2,hash_table_lock@h + ori r2,r2,hash_table_lock@l + tophys(r2,r2,r6) + li r6,0 + stw r6,0(r2) +#endif blr next_slot: .long 0 @@ -2195,6 +2227,15 @@ _GLOBAL(flush_page_to_ram) */ #ifndef CONFIG_8xx _GLOBAL(flush_hash_segments) +#ifdef __SMP__ + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l +10: lwarx r6,0,r9 + stwcx. r9,0,r9 + bne- 10b + cmpi 0,0,r6,0 + bne 10b +#endif #ifdef NO_RELOAD_HTAB /* * Bitmask of PVR numbers of 603-like chips, @@ -2231,6 +2272,12 @@ _GLOBAL(flush_hash_segments) sync 99: tlbia isync +#ifdef __SMP__ + lis r3,hash_table_lock@h + ori r3,r3,hash_table_lock@l + li r6,0 + stw r6,0(r3) +#endif blr /* @@ -2239,6 +2286,15 @@ _GLOBAL(flush_hash_segments) * flush_hash_page(unsigned context, unsigned long va) */ _GLOBAL(flush_hash_page) +#ifdef __SMP__ + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l +10: lwarx r6,0,r9 + stwcx. r9,0,r9 + bne- 10b + cmpi 0,0,r6,0 + bne 10b +#endif #ifdef NO_RELOAD_HTAB mfspr r0,PVR rlwinm r0,r0,16,27,31 @@ -2280,6 +2336,12 @@ _GLOBAL(flush_hash_page) 4: sync 99: tlbie r4 /* in hw tlb too */ isync +#ifdef __SMP__ + lis r3,hash_table_lock@h + ori r3,r3,hash_table_lock@l + li r6,0 + stw r6,0(r3) +#endif blr #endif /* CONFIG_8xx */ /* diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index a180e5f0a781..ccc5b466cb97 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -1,4 +1,6 @@ /* + * $Id: irq.c,v 1.90 1998/12/10 02:39:46 cort Exp $ + * * arch/ppc/kernel/irq.c * * Derived from arch/i386/kernel/irq.c @@ -6,6 +8,7 @@ * Adapted from arch/i386 by Gary Thomas * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Updated and modified by Cort Dougan (cort@cs.nmt.edu) + * Copyright (C) 1996 Cort Dougan * Adapted for Power Macintosh by Paul Mackerras * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). @@ -309,14 +312,14 @@ static void __openfirmware chrp_unmask_irq(unsigned int irq_nr) static void mbx_mask_irq(unsigned int irq_nr) { cached_irq_mask[0] &= ~(1 << (31-irq_nr)); - ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask = + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = cached_irq_mask[0]; } static void mbx_unmask_irq(unsigned int irq_nr) { cached_irq_mask[0] |= (1 << (31-irq_nr)); - ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask = + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = cached_irq_mask[0]; } #endif /* CONFIG_8xx */ @@ -799,9 +802,13 @@ apus_out: } if (irq < 0) { - printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", - irq, regs->nip); - spurious_interrupts++; + /* we get here with Gatwick but the 'bogus' isn't correct in that case -- Cort */ + if ( irq != second_irq ) + { + printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", + irq, regs->nip); + spurious_interrupts++; + } goto out; } @@ -809,7 +816,7 @@ apus_out: /* For MPC8xx, read the SIVEC register and shift the bits down * to get the irq number. */ - bits = ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sivec; + bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec; irq = bits >> 26; #endif /* CONFIG_8xx */ mask_and_ack_irq(irq); @@ -1089,17 +1096,6 @@ __initfunc(void init_IRQ(void)) */ if ( _prep_type == _PREP_IBM ) irq_mode2 |= 0xa0; - /* - * Sound on the Powerstack reportedly needs to be edge triggered - */ - if ( _prep_type == _PREP_Motorola ) - { - irq_mode2 &= ~0x04L; - irq_mode2 = 0xca; - outb( irq_mode1 , 0x4d0 ); - outb( irq_mode2 , 0x4d1 ); - } - } break; #ifdef CONFIG_APUS @@ -1116,8 +1112,7 @@ __initfunc(void init_IRQ(void)) /* This routine will fix some missing interrupt values in the device tree * on the gatwick mac-io controller used by some PowerBooks */ -__pmac -static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) +static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) { struct device_node *node; static struct interrupt_info int_pool[4]; diff --git a/arch/ppc/kernel/mbx_setup.c b/arch/ppc/kernel/mbx_setup.c index 9d26e27d144d..30cd01a860b6 100644 --- a/arch/ppc/kernel/mbx_setup.c +++ b/arch/ppc/kernel/mbx_setup.c @@ -1,4 +1,6 @@ /* + * $Id: mbx_setup.c,v 1.4 1998/11/15 19:58:55 cort Exp $ + * * linux/arch/ppc/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds @@ -51,10 +53,17 @@ extern int rd_image_start; /* starting block # of image */ extern char saved_command_line[256]; extern unsigned long find_available_memory(void); -extern void mbx_cpm_reset(uint); +extern void m8xx_cpm_reset(uint); +/* this really does make things cleaner -- Cort */ +void __init powermac_init(void) +{ +} +void __init adbdev_init(void) +{ +} -void mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) +void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq) { *p = 0; @@ -88,7 +97,7 @@ mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)) /* Reset the Communication Processor Module. */ - mbx_cpm_reset(cpm_page); + m8xx_cpm_reset(cpm_page); #ifdef notdef ROOT_DEV = to_kdev_t(0x0301); /* hda1 */ diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index f13508d96b33..383015cf6367 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -383,6 +383,177 @@ _GLOBAL(_set_THRM3) mtspr THRM3,r3 blr +_GLOBAL(_get_PVR) + mfspr r3,PVR + 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. + + Author: Terry Greeniaus (tgree@phys.ualberta.ca) + Please e-mail updates to this file to me, thanks! +*/ + +_GLOBAL(_set_L2CR) + /* 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 syncronous 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. + */ + + /* Make sure this is a 750 chip */ + mfspr r4,PVR + rlwinm r4,r4,16,16,31 + cmplwi r4,0x0008 + beq thisIs750 + li r3,-1 + blr + +thisIs750: + /* Get the current enable bit of the L2CR into r4 */ + mfspr r4,L2CR + rlwinm r4,r4,0,0,0 + + /* See if we want to perform a global inval this time. */ + rlwinm r6,r3,0,10,10 /* r6 contains the new invalidate bit */ + rlwinm. r5,r3,0,0,0 /* r5 contains the new enable bit */ + rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ + rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ + or r3,r3,r4 /* Keep the enable bit the same as it was for now. */ + bne dontDisableCache /* Only disable the cache if L2CRApply has the enable bit off */ + +disableCache: + /* Disable the cache. First, we turn off data relocation. */ + mfmsr r7 + rlwinm r4,r7,0,28,26 /* Turn off DR bit */ + rlwinm r4,r4,0,17,15 /* Turn off EE bit - an external exception while we are flushing + the cache is fatal (comment this line and see!) */ + sync + mtmsr r4 + sync + + /* + Now, read the first 2MB of memory to put new data in the cache. + (Actually we only need the size of the L2 cache plus + the size of the L1 cache, but 2MB will cover everything just to be safe). + */ + lis r4,0x0001 + mtctr r4 + li r4,0 +loadLoop: + lwzx r0,r0,r4 + addi r4,r4,0x0020 /* Go to start of next cache line */ + bdnz loadLoop + + /* Now, flush the first 2MB of memory */ + lis r4,0x0001 + mtctr r4 + li r4,0 + sync +flushLoop: + dcbf r0,r4 + addi r4,r4,0x0020 /* Go to start of next cache line */ + bdnz flushLoop + + /* Turn off the L2CR enable bit. */ + rlwinm r3,r3,0,1,31 + + /* Reenable data relocation. */ + sync + mtmsr r7 + sync + +dontDisableCache: + /* Set up the L2CR configuration bits */ + sync + mtspr L2CR,r3 + sync + cmplwi r6,0 + beq noInval + + /* Perform a global invalidation */ + oris r3,r3,0x0020 + sync + mtspr 1017,r3 + sync +invalCompleteLoop: /* Wait for the invalidation to complete */ + mfspr r3,1017 + rlwinm. r4,r3,0,31,31 + bne invalCompleteLoop + + rlwinm r3,r3,0,11,9; /* Turn off the L2I bit */ + sync + mtspr L2CR,r3 + sync + +noInval: + /* See if we need to enable the cache */ + cmplwi r5,0 + beqlr + +enableCache: + /* Enable the cache */ + oris r3,r3,0x8000 + mtspr L2CR,r3 + sync + blr + +_GLOBAL(_get_L2CR) + /* Make sure this is a 750 chip */ + mfspr r3,PVR + rlwinm r3,r3,16,16,31 + cmplwi r3,0x0008 + li r3,0 + bnelr + + /* Return the L2CR contents */ + mfspr r3,L2CR + blr + +/* --- End of PowerLogix code --- + */ + +/* _GLOBAL(_get_L2CR) mfspr r3,L2CR blr @@ -391,9 +562,7 @@ _GLOBAL(_set_L2CR) mtspr L2CR,r3 blr -_GLOBAL(_get_PVR) - mfspr r3,PVR - blr +*/ /* * These are used in the alignment trap handler when emulating diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 359446f4fecd..197e8344113a 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.39 1998/10/13 20:59:04 cort Exp $ + * $Id: pci.c,v 1.42 1998/12/04 14:31:37 cort Exp $ * Common pmac/prep/chrp pci routines. -- Cort */ @@ -188,13 +188,7 @@ __initfunc(void pcibios_fixup(void)) extern struct bridge_data **bridges; extern unsigned char *Motherboard_map; extern unsigned char *Motherboard_routes; - - /* - * FIXME: This is broken: We should not assign IRQ's to IRQless - * devices (look at PCI_INTERRUPT_PIN) and we also should - * honor the existence of multi-function devices where - * different functions have different interrupt pins. [mj] - */ +#ifndef CONFIG_MBX switch (_machine ) { case _MACH_prep: @@ -206,8 +200,23 @@ __initfunc(void pcibios_fixup(void)) * irq this device uses. This is necessary on things * without residual data. -- Cort */ - unsigned char d = PCI_SLOT(dev->devfn); + unsigned char d = PCI_SLOT(dev->devfn), i; dev->irq = Motherboard_routes[Motherboard_map[d]]; + for ( i = 0 ; i <= 5 ; i++ ) + { + if ( dev->base_address[i] > 0x10000000 ) + { + printk("Relocating PCI address %x -> %x\n", + dev->base_address[i], + (dev->base_address[i] & 0x00FFFFFF) + | 0x01000000); + dev->base_address[i] = + (dev->base_address[i] & 0x00FFFFFF) | 0x01000000; + pci_write_config_dword(dev, + PCI_BASE_ADDRESS_0+(i*0x4), + dev->base_address[i] ); + } + } #if 0 /* * If we have residual data and if it knows about this @@ -255,6 +264,11 @@ __initfunc(void pcibios_fixup(void)) } break; } +#else /* CONFIG_MBX */ + for(dev=pci_devices; dev; dev=dev->next) + { + } +#endif /* CONFIG_MBX */ } __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 3aa0534eaf02..30123c07653c 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -1,5 +1,5 @@ /* - * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $ + * $Id: ppc_htab.c,v 1.26 1998/12/10 00:24:23 cort Exp $ * * PowerPC hash table management proc entry. Will show information * about the current hash table and will allow changes to it. @@ -569,6 +569,7 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp, break; buffer += len; left -= len; + _set_L2CR(0); _set_L2CR(val); while ( _get_L2CR() & 0x1 ) /* wait for invalidate to finish */; diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index ea5f6db0d6a0..54db1f38161a 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -185,7 +185,9 @@ EXPORT_SYMBOL(pci_device_loc); EXPORT_SYMBOL(feature_set); EXPORT_SYMBOL(feature_clear); EXPORT_SYMBOL(feature_test); +#ifdef CONFIG_SCSI EXPORT_SYMBOL(note_scsi_host); +#endif EXPORT_SYMBOL(kd_mksound); #ifdef CONFIG_PMAC EXPORT_SYMBOL(nvram_read_byte); diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c index b7d94d2086da..b48f7a1fc00f 100644 --- a/arch/ppc/kernel/prep_pci.c +++ b/arch/ppc/kernel/prep_pci.c @@ -1,5 +1,5 @@ /* - * $Id: prep_pci.c,v 1.23 1998/10/21 10:52:24 cort Exp $ + * $Id: prep_pci.c,v 1.24 1998/12/10 02:39:51 cort Exp $ * PReP pci functions. * Originally by Gary Thomas * rewritten and updated by Cort Dougan (cort@cs.nmt.edu) @@ -107,7 +107,7 @@ static char Omaha_pci_IRQ_routes[] __prepdata = }; /* Motorola PowerStack */ -static char Blackhawk_pci_IRQ_map[16] __prepdata = +static char Blackhawk_pci_IRQ_map[19] __prepdata = { 0, /* Slot 0 - unused */ 0, /* Slot 1 - unused */ @@ -125,6 +125,9 @@ static char Blackhawk_pci_IRQ_map[16] __prepdata = 0, /* Slot 13 - unused */ 1, /* Slot 14 - Ethernet */ 0, /* Slot 15 - unused */ + 1, /* Slot P7 */ + 2, /* Slot P6 */ + 3, /* Slot P5 */ }; static char Blackhawk_pci_IRQ_routes[] __prepdata = @@ -132,7 +135,7 @@ static char Blackhawk_pci_IRQ_routes[] __prepdata = 0, /* Line 0 - Unused */ 9, /* Line 1 */ 11, /* Line 2 */ - 14, /* Line 3 */ + 15, /* Line 3 */ 15 /* Line 4 */ }; @@ -226,6 +229,7 @@ static char ibm8xx_pci_IRQ_map[23] __prepdata = { 0, /* Slot 21 - unused */ 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ }; + static char ibm8xx_pci_IRQ_routes[] __prepdata = { 0, /* Line 0 - unused */ 13, /* Line 1 */ @@ -440,6 +444,8 @@ __initfunc(unsigned long route_pci_interrupts(void)) if ( _prep_type == _PREP_Motorola) { + unsigned short irq_mode; + switch (inb(0x800) & 0xF0) { case 0x10: /* MVME16xx */ @@ -474,6 +480,14 @@ __initfunc(unsigned long route_pci_interrupts(void)) Motherboard_routes = Blackhawk_pci_IRQ_routes; break; } + /* AJF adjust level/edge control according to routes */ + irq_mode = 0; + for (i = 1; i <= 4; i++) + { + irq_mode |= ( 1 << Motherboard_routes[i] ); + } + outb( irq_mode & 0xff, 0x4d0 ); + outb( (irq_mode >> 8) & 0xff, 0x4d1 ); } else if ( _prep_type == _PREP_IBM ) { unsigned char pl_id; diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index e596f9ea5086..72752e11fe73 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -189,11 +189,6 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)) /* Enable L2. Assume we don't need to flush -- Cort*/ *(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3; - /* make the serial port the console */ - /* strcat(cmd_line,"console=ttyS0,9600n8"); */ - /* use the normal console but send output to the serial port, too */ - /*strcat(cmd_line,"console=tty0 console=ttyS0,9600n8");*/ - sprintf(cmd_line,"%s console=tty0 console=ttyS0,9600n8", cmd_line); printk("Boot arguments: %s\n", cmd_line); #ifdef CONFIG_SOUND_CS4232 diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 5ea55cee9200..11d72054a0d1 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -1,4 +1,6 @@ /* + * $Id: process.c,v 1.68 1998/11/15 19:59:02 cort Exp $ + * * linux/arch/ppc/kernel/process.c * * Derived from "arch/i386/kernel/process.c" @@ -450,6 +452,7 @@ print_backtrace(unsigned long *sp) printk("\n"); } +#if 0 /* * Low level print for debugging - Cort */ @@ -537,3 +540,4 @@ __initfunc(void ll_puts(const char *s)) orig_x = x; orig_y = y; } +#endif diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 706c1dde2f2a..b52f6d92b1c4 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.117 1998/11/09 19:55:53 geert Exp $ + * $Id: setup.c,v 1.120 1998/12/10 00:24:28 cort Exp $ * Common prep/pmac/chrp boot and setup code. */ @@ -35,7 +35,7 @@ extern unsigned long m68k_machtype; extern int parse_bootinfo(const struct bi_record *); extern char _end[]; #ifdef CONFIG_APUS -struct mem_info ramdisk; +extern struct mem_info ramdisk; unsigned long isa_io_base; unsigned long isa_mem_base; unsigned long pci_dram_offset; @@ -665,7 +665,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, #else /* CONFIG_MBX */ if ( r3 ) - memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); + memcpy( (void *)res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); #ifdef CONFIG_PCI setup_pci_ptrs(); @@ -693,9 +693,22 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, extern int __map_without_bats; __map_without_bats = 1; } + return 0; } +/* Checks "l2cr=xxxx" command-line option */ +void ppc_setup_l2cr(char *str, int *ints) +{ + if ( (_get_PVR() >> 16) == 8) + { + unsigned long val = simple_strtoul(str, NULL, 0); + printk(KERN_INFO "l2cr set to %lx\n", val); + _set_L2CR(0); + _set_L2CR(val); + } +} + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index 75445925f83c..e6dca0e806d5 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -1,5 +1,5 @@ /* - * $Id: smp.c,v 1.36 1998/10/08 01:17:48 cort Exp $ + * $Id: smp.c,v 1.38 1998/12/02 21:23:49 cort Exp $ * * Smp support for ppc. * @@ -152,7 +152,7 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait) { if ( _machine != _MACH_Pmac ) return; - /*printk("SMP %d: sending smp message\n", current->processor);*/ +printk("SMP %d: sending smp message %x\n", current->processor, msg); if (smp_processor_id() ) printk("pass from cpu 1\n"); spin_lock(&mesg_pass_lock); #define OTHER (~smp_processor_id() & 1) @@ -179,7 +179,7 @@ if (smp_processor_id() ) printk("pass from cpu 1\n"); spin_unlock(&mesg_pass_lock); } -__initfunc(void smp_boot_cpus(void)) +void __init smp_boot_cpus(void) { extern struct task_struct *current_set[NR_CPUS]; extern void __secondary_start(void); @@ -251,19 +251,17 @@ __initfunc(void smp_boot_cpus(void)) smp_message_pass(1,0xf0f0, 0, 0); } -__initfunc(void smp_commence(void)) +void __init smp_commence(void) { printk("SMP %d: smp_commence()\n",current->processor); /* * Lets the callin's below out of their loop. */ - local_flush_tlb_all(); smp_commenced = 1; - local_flush_tlb_all(); } /* intel needs this */ -__initfunc(void initialize_secondary(void)) +void __init initialize_secondary(void) { } @@ -275,33 +273,33 @@ asmlinkage int __init start_secondary(void *unused) return cpu_idle(NULL); } -__initfunc(void smp_callin(void)) +void __init smp_callin(void) { printk("SMP %d: smp_callin()\n",current->processor); smp_store_cpu_info(current->processor); set_dec(decrementer_count); - +#if 0 current->mm->mmap->vm_page_prot = PAGE_SHARED; current->mm->mmap->vm_start = PAGE_OFFSET; current->mm->mmap->vm_end = init_task.mm->mmap->vm_end; - - cpu_callin_map[current->processor] = current->processor; +#endif + cpu_callin_map[current->processor] = 1; while(!smp_commenced) barrier(); __sti(); } -__initfunc(void smp_setup(char *str, int *ints)) +void __init smp_setup(char *str, int *ints) { printk("SMP %d: smp_setup()\n",current->processor); } -__initfunc(int setup_profiling_timer(unsigned int multiplier)) +int __init setup_profiling_timer(unsigned int multiplier) { return 0; } -__initfunc(void smp_store_cpu_info(int id)) +void __init smp_store_cpu_info(int id) { struct cpuinfo_PPC *c = &cpu_data[id]; diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index 8bada0e6961a..0842f52fbe03 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -1,5 +1,5 @@ /* - * $Id: time.c,v 1.36 1998/10/10 12:16:08 geert Exp $ + * $Id: time.c,v 1.38 1998/11/16 15:56:15 cort Exp $ * Common time routines among all ppc machines. * * Written by Cort Dougan (cort@cs.nmt.edu) to merge @@ -133,9 +133,9 @@ void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) static int mbx_set_rtc_time(unsigned long time) { - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY; return(0); } #endif /* CONFIG_MBX */ @@ -227,13 +227,13 @@ __initfunc(void time_init(void)) * modify these registers we have to write the key value to * the key location associated with the register. */ - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; + ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; /* Disable the RTC one second and alarm interrupts. */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &= + ((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &= ~(RTCSC_SIE | RTCSC_ALE); /* Enabling the decrementer also enables the timebase interrupts @@ -241,7 +241,7 @@ __initfunc(void time_init(void)) * we have to enable the timebase). The decrementer interrupt * is wired into the vector table, nothing to do here for that. */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr = + ((immap_t *)IMAP_ADDR)->im_sit.sit_tbscr = ((mk_int_int_mask(DEC_INTERRUPT) << 8) | (TBSCR_TBF | TBSCR_TBE)); if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0) @@ -249,7 +249,7 @@ __initfunc(void time_init(void)) /* Get time from the RTC. */ - xtime.tv_sec = ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc; + xtime.tv_sec = ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc; xtime.tv_usec = 0; #endif /* CONFIG_MBX */ @@ -343,10 +343,10 @@ __initfunc(void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * */ __initfunc(void mbx_calibrate_decr(void)) { - bd_t *binfo = (bd_t *)&res; + bd_t *binfo = (bd_t *)res; int freq, fp, divisor; - if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) + if ((((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) printk("WARNING: Wrong decrementer source clock.\n"); /* The manual says the frequency is in Hz, but it is really diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index 8ca9a3cd5466..4cc49de17f37 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile @@ -8,7 +8,7 @@ O_TARGET = lib.o O_OBJS = checksum.o string.o strcase.o -ifdef CONFIG_SMP +ifdef SMP O_OBJS += locks.o endif diff --git a/arch/ppc/mbx_defconfig b/arch/ppc/mbx_defconfig index 5a2e7960bc22..4882740c5d98 100644 --- a/arch/ppc/mbx_defconfig +++ b/arch/ppc/mbx_defconfig @@ -14,16 +14,16 @@ CONFIG_8xx=y # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set CONFIG_MBX=y -# CONFIG_SMP is not set -CONFIG_SERIAL_CONSOLE=y CONFIG_MACH_SPECIFIC=y +CONFIG_SERIAL_CONSOLE=y # # General setup # -# CONFIG_EXPERIMENTAL is not set +CONFIG_EXPERIMENTAL=y # CONFIG_MODULES is not set CONFIG_PCI=y +# CONFIG_PCI_QUIRKS is not set CONFIG_PCI_OLD_PROC=y CONFIG_NET=y # CONFIG_SYSCTL is not set @@ -34,13 +34,19 @@ CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_BINFMT_JAVA is not set # CONFIG_PARPORT is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_FB is not set +# CONFIG_PMAC_PBOOK is not set # CONFIG_MAC_KEYBOARD is not set # CONFIG_MAC_FLOPPY is not set # CONFIG_MAC_SERIAL is not set +# CONFIG_ADBMOUSE is not set +# CONFIG_BLK_DEV_IDE_PMAC is not set # CONFIG_PROC_DEVICETREE is not set # CONFIG_KGDB is not set # CONFIG_XMON is not set -CONFIG_VGA_CONSOLE=y +# CONFIG_TOTALMP is not set +# CONFIG_BOOTX_TEXT is not set # # Plug and Play support @@ -48,7 +54,7 @@ CONFIG_VGA_CONSOLE=y # CONFIG_PNP is not set # -# Floppy, IDE, and other block devices +# Block devices # # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_IDE is not set @@ -85,8 +91,19 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_RARP is not set CONFIG_IP_NOSR=y # CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set +# CONFIG_NET_SCHED is not set # # SCSI support @@ -101,22 +118,26 @@ CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set CONFIG_NET_ETHERNET=y +# CONFIG_MACE is not set +# CONFIG_BMAC is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set +# CONFIG_HIPPI is not set # CONFIG_DLCI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set # CONFIG_NET_RADIO is not set # CONFIG_TR is not set -# CONFIG_WAN_DRIVERS is not set -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set # # Amateur Radio support @@ -133,6 +154,32 @@ CONFIG_NET_ETHERNET=y # # CONFIG_CD_NO_IDESCSI is not set +# +# Console drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_NVRAM is not set +# CONFIG_JOYSTICK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + # # Filesystems # @@ -160,30 +207,14 @@ CONFIG_LOCKD=y # CONFIG_ROMFS_FS is not set # CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SMD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_ADFS_FS is not set +# CONFIG_QNX4FS_FS is not set # CONFIG_MAC_PARTITION is not set # CONFIG_NLS is not set -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_MOUSE is not set -# CONFIG_QIC02_TAPE is not set -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_VIDEO_DEV is not set -# CONFIG_NVRAM is not set -# CONFIG_JOYSTICK is not set -# CONFIG_MISC_RADIO is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set - # # Sound # diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 44104fd4e26f..72bffcc5764e 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -1,5 +1,5 @@ /* - * $Id: init.c,v 1.130 1998/11/10 10:09:20 paulus Exp $ + * $Id: init.c,v 1.138 1998/12/15 17:34:43 cort Exp $ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -55,7 +55,7 @@ /* END APUS includes */ int prom_trashed; -int next_mmu_context; +atomic_t next_mmu_context; unsigned long *end_of_DRAM; int mem_init_done; extern pgd_t swapper_pg_dir[]; @@ -71,7 +71,8 @@ unsigned long ioremap_base; unsigned long ioremap_bot; unsigned long avail_start; struct pgtable_cache_struct quicklists; -struct mem_info memory[NUM_MEMINFO]; +extern int num_memory; +extern struct mem_info memory[NUM_MEMINFO]; extern boot_infos_t *boot_infos; void MMU_init(void); @@ -89,6 +90,27 @@ void map_page(struct task_struct *, unsigned long va, extern void die_if_kernel(char *,struct pt_regs *,long); extern void show_net_buffers(void); + +/* + * The following stuff defines a data structure for representing + * areas of memory as an array of (address, length) pairs, and + * procedures for manipulating them. + */ +#define MAX_MEM_REGIONS 32 + +struct mem_pieces { + int n_regions; + struct reg_property regions[MAX_MEM_REGIONS]; +}; +struct mem_pieces phys_mem; +struct mem_pieces phys_avail; +struct mem_pieces prom_mem; + +static void remove_mem_piece(struct mem_pieces *, unsigned, unsigned, int); +void *find_mem_piece(unsigned, unsigned); +static void print_mem_pieces(struct mem_pieces *); +static void append_mem_piece(struct mem_pieces *, unsigned, unsigned); + extern struct task_struct *current_set[NR_CPUS]; PTE *Hash, *Hash_end; @@ -529,37 +551,18 @@ mmu_context_overflow(void) } read_unlock(&tasklist_lock); flush_hash_segments(0x10, 0xffffff); - next_mmu_context = 0; + atomic_set(&next_mmu_context, 0); /* make sure current always has a context */ - current->mm->context = MUNGE_CONTEXT(++next_mmu_context); + current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context)); set_context(current->mm->context); #else /* We set the value to -1 because it is pre-incremented before * before use. */ - next_mmu_context = -1; + atomic_set(&next_mmu_context, -1); #endif } -/* - * The following stuff defines a data structure for representing - * areas of memory as an array of (address, length) pairs, and - * procedures for manipulating them. - */ -#define MAX_MEM_REGIONS 32 - -struct mem_pieces { - int n_regions; - struct reg_property regions[MAX_MEM_REGIONS]; -}; -struct mem_pieces phys_mem; -struct mem_pieces phys_avail; -struct mem_pieces prom_mem; - -static void remove_mem_piece(struct mem_pieces *, unsigned, unsigned, int); -void *find_mem_piece(unsigned, unsigned); -static void print_mem_pieces(struct mem_pieces *); - /* * Scan a region for a piece of a given size with the required alignment. */ @@ -653,14 +656,26 @@ __initfunc(static void print_mem_pieces(struct mem_pieces *mp)) printk("\n"); } +/* + * Add some memory to an array of pieces + */ +__initfunc(static void + append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size)) +{ + struct reg_property *rp; + if (mp->n_regions >= MAX_MEM_REGIONS) + return; + rp = &mp->regions[mp->n_regions++]; + rp->address = start; + rp->size = size; +} #ifndef CONFIG_8xx static void hash_init(void); static void get_mem_prop(char *, struct mem_pieces *); static void sort_mem_pieces(struct mem_pieces *); static void coalesce_mem_pieces(struct mem_pieces *); -static void append_mem_piece(struct mem_pieces *, unsigned, unsigned); __initfunc(static void sort_mem_pieces(struct mem_pieces *mp)) { @@ -702,21 +717,6 @@ __initfunc(static void coalesce_mem_pieces(struct mem_pieces *mp)) mp->n_regions = d; } -/* - * Add some memory to an array of pieces - */ -__initfunc(static void - append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size)) -{ - struct reg_property *rp; - - if (mp->n_regions >= MAX_MEM_REGIONS) - return; - rp = &mp->regions[mp->n_regions++]; - rp->address = start; - rp->size = size; -} - /* * Read in a property describing some pieces of memory. */ @@ -963,8 +963,10 @@ __initfunc(void MMU_init(void)) #ifndef CONFIG_8xx if (have_of) end_of_DRAM = pmac_find_end_of_memory(); +#ifdef CONFIG_APUS else if (_machine == _MACH_apus ) end_of_DRAM = apus_find_end_of_memory(); +#endif else /* prep */ end_of_DRAM = prep_find_end_of_memory(); @@ -1023,7 +1025,7 @@ __initfunc(void MMU_init(void)) */ ioremap(NVRAM_ADDR, NVRAM_SIZE); ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE); - ioremap(MBX_IMAP_ADDR, MBX_IMAP_SIZE); + ioremap(IMAP_ADDR, IMAP_SIZE); ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE); #endif /* CONFIG_8xx */ } @@ -1189,7 +1191,7 @@ __initfunc(unsigned long *mbx_find_end_of_memory(void)) volatile memctl8xx_t *mcp; unsigned long *ret; - binfo = (bd_t *)&res; + binfo = (bd_t *)res; /* * The MBX does weird things with the mmaps for ram. @@ -1200,11 +1202,13 @@ __initfunc(unsigned long *mbx_find_end_of_memory(void)) * In fact, it might be the best idea to just read the DRAM * config registers and set the mem areas accordingly. */ - mcp = (memctl8xx_t *)(&(((immap_t *)MBX_IMAP_ADDR)->im_memctl)); + mcp = (memctl8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_memctl)); + append_mem_piece(&phys_mem, 0, binfo->bi_memsize); +#if 0 phys_mem.regions[0].address = 0; - phys_mem.regions[0].size = binfo->bi_memsize; - + phys_mem.regions[0].size = binfo->bi_memsize; phys_mem.n_regions = 1; +#endif ret = __va(phys_mem.regions[0].address+ phys_mem.regions[0].size); @@ -1322,6 +1326,7 @@ __initfunc(unsigned long *prep_find_end_of_memory(void)) return (__va(total)); } +#ifdef CONFIG_APUS #define HARDWARE_MAPPED_SIZE (512*1024) __initfunc(unsigned long *apus_find_end_of_memory(void)) { @@ -1381,15 +1386,22 @@ __initfunc(unsigned long *apus_find_end_of_memory(void)) /* Remove the upper 512KB where the PPC exception vectors are mapped. */ top -= HARDWARE_MAPPED_SIZE; - remove_mem_piece(&phys_avail, top, - HARDWARE_MAPPED_SIZE, 0); +#if 0 + /* This would be neat, but it breaks on A3000 machines!? */ + remove_mem_piece(&phys_avail, top, 16384, 0); +#else + remove_mem_piece(&phys_avail, top, HARDWARE_MAPPED_SIZE, 0); +#endif + } - /* FIXME:APUS: Only handles one block of memory! Problem is - that the VTOP/PTOV code in head.S would be a mess if it had - to handle more than one block. */ + /* Linux/APUS only handles one block of memory -- the one on + the PowerUP board. Other system memory is horrible slow in + comparison. The user can use other memory for swapping + using the z2ram device. */ return __va(memory[0].addr + memory[0].size); } +#endif /* CONFIG_APUS */ /* * Initialize the hash table and patch the instructions in head.S. @@ -1400,7 +1412,7 @@ __initfunc(static void hash_init(void)) unsigned long h, ramsize; extern unsigned int hash_page_patch_A[], hash_page_patch_B[], - hash_page_patch_C[]; + hash_page_patch_C[], hash_page[]; /* * Allow 64k of hash table for every 16MB of memory, @@ -1475,7 +1487,17 @@ __initfunc(static void hash_init(void)) flush_icache_range((unsigned long) b(hash_page_patch_A), (unsigned long) b(hash_page_patch_C + 1)); } - else + 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. + */ + *b(hash_page) = 0x4e800020; + flush_icache_range((unsigned long) b(hash_page), + (unsigned long) b(hash_page + 1)); + } } #endif /* ndef CONFIG_8xx */ + diff --git a/arch/ppc/pmac_defconfig b/arch/ppc/pmac_defconfig index b0c9ad966f43..ae1303bb4813 100644 --- a/arch/ppc/pmac_defconfig +++ b/arch/ppc/pmac_defconfig @@ -14,7 +14,6 @@ CONFIG_PMAC=y # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set # CONFIG_MBX is not set -# CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # diff --git a/arch/ppc/prep_defconfig b/arch/ppc/prep_defconfig index 14b4ea4a0ffc..41db35a4a4a9 100644 --- a/arch/ppc/prep_defconfig +++ b/arch/ppc/prep_defconfig @@ -14,7 +14,6 @@ CONFIG_PREP=y # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set # CONFIG_MBX is not set -# CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 13ce064f4880..30ecbd4e0b0f 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -180,7 +180,7 @@ check_media_bay(struct device_node *which_bay, int what) { #ifdef CONFIG_BLK_DEV_IDE int i; - + for (i=0; i 1000) { printk(KERN_DEBUG "PMU: stuck in intr loop, " "intr=%x pmu_state=%d\n", intr, pmu_state); @@ -534,6 +534,12 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs) else if (intr & CB1_INT) { adb_int_pending = 1; out_8(&via[IFR], CB1_INT); + } else + { + /* -- Disabled printk, will happen _really_ often on + PowerBooks ((CB2 interrupts) -- + printk(KERN_DEBUG "PMU: spurrious interrupt intr=%x\n", intr); */ + out_8(&via[IFR], intr); } } if (pmu_state == idle) { @@ -750,7 +756,8 @@ pmu_restart(void) _disable_interrupts(); - pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT); + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | + PMU_INT_TICK ); while(!req.complete) pmu_poll(); @@ -768,7 +775,8 @@ pmu_shutdown(void) _disable_interrupts(); - pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT); + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | + PMU_INT_TICK ); while(!req.complete) pmu_poll(); diff --git a/drivers/video/Config.in b/drivers/video/Config.in index b5b27c14a8c2..465b22d5861b 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -156,7 +156,8 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ - "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" ]; then + "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ + "$CONFIG_FB_CT65550" = "y" ]; then define_bool CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ @@ -168,7 +169,8 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ - "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" ]; then + "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ + "$CONFIG_FB_CT65550" = "m" ]; then define_bool CONFIG_FBCON_CFB8 m fi fi @@ -178,7 +180,7 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ - "$CONFIG_FB_MATROX" = "y" ]; then + "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" ]; then define_bool CONFIG_FBCON_CFB16 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ @@ -187,7 +189,7 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ - "$CONFIG_FB_MATROX" = "m" ]; then + "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" ]; then define_bool CONFIG_FBCON_CFB16 m fi fi diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index e3f1b1d8d3a1..84585f6fea5a 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.90 1998/11/20 12:27:03 geert Exp $ +/* $Id: atyfb.c,v 1.93 1998/12/18 18:33:13 geert Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -1457,7 +1457,7 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per) vco_div_count = pll->m & 0x3f; ref_div_count = pll->n; - *vclk_per = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df); + *vclk_per = ((ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65); return 0; } @@ -1719,6 +1719,22 @@ static void atyfb_set_par(const struct atyfb_par *par, aty_set_pll_gx(info, &par->pll.gx); aty_st_le32(BUS_CNTL, 0x890e20f1, info); aty_st_le32(DAC_CNTL, 0x47052100, info); + + /* Don't forget MEM_CNTL */ + i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff; + switch (par->crtc.bpp) { + case 8: + i |= 0x02000000; + break; + case 16: + i |= 0x03000000; + break; + case 32: + i |= 0x06000000; + break; + } + aty_st_le32(MEM_CNTL, i, info); + } else { aty_set_pll_ct(info, &par->pll.ct); i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff; diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c index 4e0bc74ed814..2891b4877419 100644 --- a/drivers/video/cgsixfb.c +++ b/drivers/video/cgsixfb.c @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.11 1998/09/04 15:43:42 jj Exp $ +/* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -534,6 +534,7 @@ static void cg6_reset (struct fb_info_sbusfb *fb) unsigned int rev, conf; struct cg6_tec *tec = fb->s.cg6.tec; struct cg6_fbc *fbc = fb->s.cg6.fbc; + u32 mode; /* Turn off stuff in the Transform Engine. */ tec->tec_matrix = 0; @@ -552,15 +553,20 @@ static void cg6_reset (struct fb_info_sbusfb *fb) *(fb->s.cg6.fhc) = conf; } - /* Set things in the FBC. */ - fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | + /* Set things in the FBC. Bad things appear to happen if we do + * back to back store/loads on the mode register, so copy it + * out instead. */ + mode = fbc->mode; + mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | CG6_FBC_BDISP_MASK); - fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 | + mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 | CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | CG6_FBC_BDISP_0); + fbc->mode = mode; + fbc->clip = 0; fbc->offx = 0; fbc->offy = 0; diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 699ae96ff409..04735949e496 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -358,6 +358,7 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in if (con == currcon) { write_cr(0x13, 200); // 16 bit display width (decimal) write_xr(0x81, 0x14); // 15 bit (TrueColor) color mode + write_xr(0x82, 0x00); // disable palettes write_xr(0x20, 0x10); // 16 bit blitter mode } @@ -379,6 +380,7 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in if (con == currcon) { write_cr(0x13, 100); // 8 bit display width (decimal) write_xr(0x81, 0x12); // 8 bit color mode + write_xr(0x82, 0x08); // Graphics gamma enable write_xr(0x20, 0x00); // 8 bit blitter mode } diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index d1a63b64fef8..129c4e396971 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -57,12 +57,6 @@ #include "controlfb.h" -static int currcon = 0; -static int switching = 0; -static char fontname[40] __initdata = { 0 }; -static int default_vmode = VMODE_NVRAM; -static int default_cmode = CMODE_NVRAM; - struct fb_par_control { int vmode, cmode; int xres, yres; @@ -70,11 +64,25 @@ struct fb_par_control { int xoffset, yoffset; }; +#define DIRTY(z) ((x)->z != (y)->z) +static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y) +{ + return (!DIRTY(vmode) && !DIRTY(cmode) && !DIRTY(xres) + && !DIRTY(yres) && !DIRTY(vxres) && !DIRTY(vyres) + && !DIRTY(xoffset) && !DIRTY(yoffset)); +} +static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y) +{ + return (!DIRTY(bits_per_pixel) && !DIRTY(xres) + && !DIRTY(yres) && !DIRTY(xres_virtual) + && !DIRTY(yres_virtual)); +} + struct fb_info_control { struct fb_info info; - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; - struct display disp; +/* struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var;*/ + struct display display; struct fb_par_control par; struct { __u8 red, green, blue; @@ -101,15 +109,7 @@ struct fb_info_control { } fbcon_cmap; }; -/* - * Exported functions - */ -void control_init(void); -#ifdef CONFIG_FB_OF -void control_of_init(struct device_node *dp); -#endif -void controlfb_setup(char *options, int *ints); - +/******************** Prototypes for exported functions ********************/ static int control_open(struct fb_info *info, int user); static int control_release(struct fb_info *info, int user); static int control_get_fix(struct fb_fix_screeninfo *fix, int con, @@ -127,11 +127,38 @@ static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int control_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info); + +static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info); +static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); + +/******************** Prototypes for internal functions ********************/ +static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, + struct fb_info_control *p); +static void do_install_cmap(int con, struct fb_info *info); +static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p); + +/************************* Internal variables *****************************/ +static int currcon = 0; +static int par_set = 0; +static char fontname[40] __initdata = { 0 }; +static int default_vmode = VMODE_NVRAM; +static int default_cmode = CMODE_NVRAM; + +/* + * Exported functions + */ +void control_init(void); +#ifdef CONFIG_FB_OF +void control_of_init(struct device_node *dp); +#endif +void control_setup(char *options, int *ints); + static int read_control_sense(struct fb_info_control *p); static inline int control_vram_reqd(int video_mode, int color_mode); static void set_control_clock(unsigned char *params); -static void control_set_hardware(struct fb_info_control *p); -static void control_par_to_all(struct fb_info_control *p, int init); +static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par); static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var); static int control_var_to_par(struct fb_var_screeninfo *var, struct fb_par_control *par, const struct fb_info *fb_info); @@ -139,10 +166,8 @@ static int control_var_to_par(struct fb_var_screeninfo *var, static void control_init_info(struct fb_info *info, struct fb_info_control *p); static void control_par_to_display(struct fb_par_control *par, struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p); -static void control_init_display(struct display *disp); -static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, - struct fb_info_control *p); -static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p); + +static int controlfb_updatevar(int con, struct fb_info *info); static struct fb_ops controlfb_ops = { control_open, @@ -156,15 +181,15 @@ static struct fb_ops controlfb_ops = { control_ioctl }; -static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, - u_int *blue, u_int *transp, struct fb_info *info); -static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); -static void do_install_cmap(int con, struct fb_info *info); +/******************** The functions for controlfb_ops ********************/ + +#ifndef MODULE __openfirmware +#endif +/********** Dummies for loading control as a module **********/ static int control_open(struct fb_info *info, int user) { @@ -178,25 +203,62 @@ static int control_release(struct fb_info *info, int user) return 0; } +#ifdef MODULE +int init_module(void) +{ + struct device_node *dp; + + printk("Loading...\n"); + dp = find_devices("control"); + if (dp != 0) + control_of_init(dp); + else + printk("Failed.\n"); + printk("Done.\n"); +} + +void cleanup_module(void) +{ +} +#endif + +/*********** Providing our information to the user ************/ + static int control_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) { - struct fb_info_control *cp = (struct fb_info_control *) info; + struct fb_info_control *p = (struct fb_info_control *) info; - *fix = cp->fix; + if(!par_set) + printk(KERN_ERR "control_get_fix called with unset par!\n"); + if(con == -1) { + control_par_to_fix(&p->par, fix, p); + } else { + struct fb_par_control par; + + control_var_to_par(&fb_display[con].var, &par, info); + control_par_to_fix(&par, fix, p); + } return 0; } static int control_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - struct fb_info_control *cp = (struct fb_info_control *) info; + struct fb_info_control *p = (struct fb_info_control *) info; - *var = cp->var; + if(!par_set) + printk(KERN_ERR "control_get_var called with unset par!\n"); + if(con == -1) { + control_par_to_var(&p->par, var); + } else { + *var = fb_display[con].var; + } return 0; } /* Sets everything according to var */ +/* No longer safe for use in console switching */ static int control_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { @@ -204,53 +266,57 @@ static int control_set_var(struct fb_var_screeninfo *var, int con, struct display *disp; struct fb_par_control par; int depthchange, err; + int activate = var->activate; + + disp = (con >= 0) ? &fb_display[con] : info->disp; - disp = (con >= 0) ? &fb_display[con] : &p->disp; if((err = control_var_to_par(var, &par, info))) { - printk (KERN_ERR "Error in control_set_var, calling control_var_to_par: %d.\n", err); + printk (KERN_ERR "control_set_var: error calling control_var_to_par: %d.\n", err); return err; } - if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) { - /* printk("Not activating, in control_set_var.\n"); */ - control_par_to_var(&par, var); + control_par_to_var(&par, var); + + if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) return 0; - } + /* I know, we want to use fb_display[con], but grab certain info from p->var instead. */ -#define DIRTY(x) (p->var.x != var->x) - depthchange = DIRTY(bits_per_pixel); - if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) && - !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel)) { - control_par_to_var(&par, var); - p->var = disp->var = *var; - return 0; - } - /* printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel); */ - /* OK, we're getting here at the right times... */ - p->par = par; - control_par_to_var(&par, var); - p->var = *var; - control_par_to_fix(&par, &p->fix, p); - control_par_to_display(&par, disp, &p->fix, p); - p->disp = *disp; +/* [above no longer true] */ + depthchange = (disp->var.bits_per_pixel != var->bits_per_pixel); + if(!VAR_MATCH(&disp->var, var)) { + struct fb_fix_screeninfo fix; + control_par_to_fix(&par, &fix, p); + control_par_to_display(&par, disp, &fix, p); + if(info->changevar) + (*info->changevar)(con); + } else + disp->var = *var; + /*p->disp = *disp;*/ + - if(info->changevar && !switching) /* Don't want to do this if just switching consoles. */ - (*info->changevar)(con); - if(con == currcon) - control_set_hardware(p); - if(depthchange) + if(con == currcon || con == -1) { + control_set_hardware(p, &par); + } + if(depthchange) { if((err = fb_alloc_cmap(&disp->cmap, 0, 0))) return err; - if(depthchange || switching) do_install_cmap(con, info); + } return 0; } static int control_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - if (var->xoffset != 0 || var->yoffset != 0) + struct fb_info_control *p = (struct fb_info_control *)info; + struct fb_par_control *par = &p->par; + + if (var->xoffset != 0 || var->yoffset+var->yres > var->yres_virtual) return -EINVAL; + fb_display[con].var.yoffset = par->yoffset = var->yoffset; + if(con == currcon) + out_le32(&p->control_regs->start_addr.r, + par->yoffset * (par->vxres << par->cmode)); return 0; } @@ -260,7 +326,7 @@ static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con, if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, controlfb_getcolreg, info); if (fb_display[con].cmap.len) /* non default colormap? */ - fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2); + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0: 2); else { int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); @@ -275,12 +341,11 @@ static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con, int err; if (disp->cmap.len == 0) { - int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + int size = disp->var.bits_per_pixel == 16 ? 32 : 256; err = fb_alloc_cmap(&disp->cmap, size, 0); if (err) return err; } - if (con == currcon) return fb_set_cmap(cmap, kspc, controlfb_setcolreg, info); fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); @@ -293,30 +358,42 @@ static int control_ioctl(struct inode *inode, struct file *file, u_int cmd, return -EINVAL; } +/******************** End of controlfb_ops implementation ********************/ +/* (new one that is) */ + + static int controlfb_switch(int con, struct fb_info *info) { + struct fb_info_control *p = (struct fb_info_control *)info; + struct fb_par_control par; + int oldcon = currcon; + if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, controlfb_getcolreg, info); currcon = con; -#if 0 - control_var_to_par(&fb_display[currcon].var, &par, info); - control_set_par(&par, info); /*STOPPEDHERE - did i define that? */ + + control_var_to_par(&fb_display[con].var, &par, info); + control_set_hardware(p, &par); + control_set_dispsw(&fb_display[con], par.cmode, p); + + if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset); + controlfb_updatevar(con, info); + do_install_cmap(con, info); -#else - /* I see no reason not to do this. Minus info->changevar(). */ - /* DOH. This makes control_set_var compare, you guessed it, */ - /* fb_display[con].var (first param), and fb_display[con].var! */ - /* Perhaps I just fixed that... */ - switching = 1; - control_set_var(&fb_display[con].var, con, info); - switching = 0; -#endif - return 0; + return 1; } static int controlfb_updatevar(int con, struct fb_info *info) { + struct fb_info_control *p = (struct fb_info_control *)info; + + if(con != currcon) + return 0; + /* imsttfb blanks the unused bottom of the screen here...hmm. */ + out_le32(&p->control_regs->start_addr.r, + fb_display[con].var.yoffset * fb_display[con].line_length); + return 0; } @@ -332,10 +409,12 @@ static void controlfb_blank(int blank_mode, struct fb_info *info) * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown */ -/* [danj] I think there's something fishy about those constants... */ +/* A blank_mode of 1+VESA_NO_BLANKING or 1+VESA_POWERDOWN act alike... */ struct fb_info_control *p = (struct fb_info_control *) info; int ctrl; + if(blank_mode == 1+VESA_NO_BLANKING) + blank_mode = 1+VESA_POWERDOWN; ctrl = ld_le32(&p->control_regs->ctrl.r) | 0x33; if (blank_mode) --blank_mode; @@ -385,25 +464,16 @@ static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, out_8(&p->cmap_regs->lut, blue); if (regno < 16) - switch (p->var.bits_per_pixel) { + switch (p->par.cmode) { #ifdef FBCON_HAS_CFB16 - case 16: -#if 0 - p->fbcon_cmap.cfb16[regno] = (red << 10) | (green << 5) | blue; -#else + case CMODE_16: p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno; -#endif break; #endif #ifdef FBCON_HAS_CFB32 - case 32: -#if 0 - p->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue; -#else + case CMODE_32: i = (regno << 8) | regno; p->fbcon_cmap.cfb32[regno] = (i << 16) | i; - /* I think */ -#endif break; #endif } @@ -427,18 +497,12 @@ static void do_install_cmap(int con, struct fb_info *info) #ifdef CONFIG_FB_COMPAT_XPMAC extern struct vc_mode display_info; extern struct fb_info *console_fb_info; -#if 0 -extern int (*console_setmode_ptr)(struct vc_mode *, int); -extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, - struct fb_info *); -int console_setmode(struct vc_mode *, int); -#endif #endif /* CONFIG_FB_COMPAT_XPMAC */ static inline int control_vram_reqd(int video_mode, int color_mode) { return control_reg_init[video_mode-1]->vres - * control_reg_init[video_mode-1]->pitch[color_mode]; + * control_reg_init[video_mode-1]->hres << color_mode; } static void set_control_clock(unsigned char *params) @@ -457,7 +521,9 @@ static void set_control_clock(unsigned char *params) __initfunc(static void init_control(struct fb_info_control *p)) { - struct fb_par_control *par = &p->par; + struct fb_par_control parstruct; + struct fb_par_control *par = &parstruct; + struct fb_var_screeninfo var; p->sense = read_control_sense(p); printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense); @@ -482,30 +548,44 @@ __initfunc(static void init_control(struct fb_info_control *p)) printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode); par->vxres = par->xres = control_reg_init[par->vmode - 1]->hres; - par->vyres = par->yres = control_reg_init[par->vmode - 1]->vres; + par->yres = control_reg_init[par->vmode - 1]->vres; + par->vyres = p->total_vram / (par->vxres << par->cmode); par->xoffset = par->yoffset = 0; - control_par_to_all(p, 1); + control_init_info(&p->info, p); + + par_set = 1; /* Debug */ + + control_par_to_var(par, &var); + control_set_var(&var, -1, &p->info); p->info.flags = FBINFO_FLAG_DEFAULT; if (register_framebuffer(&p->info) < 0) { kfree(p); return; } - control_set_hardware(p); printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node)); } +#define STORE_D2(a,d) \ + out_8(&p->cmap_regs->addr, (a)); \ + out_8(&p->cmap_regs->d2, (d)) + /* Now how about actually saying, Make it so! */ /* Some things in here probably don't need to be done each time. */ -static void control_set_hardware(struct fb_info_control *p) +static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par) { struct control_regvals *init; - struct preg *rp; + volatile struct preg *rp; int flags, ctrl, i; int vmode, cmode; + if(PAR_EQUAL(&p->par, par)) + return; + + p->par = *par; + vmode = p->par.vmode; cmode = p->par.cmode; @@ -527,19 +607,20 @@ static void control_set_hardware(struct fb_info_control *p) set_control_clock(init->clock_params); - p->cmap_regs->addr = 0x20; p->cmap_regs->d2 = init->radacal_ctrl[cmode]; - p->cmap_regs->addr = 0x21; p->cmap_regs->d2 = p->control_use_bank2 ? 0: 1; - p->cmap_regs->addr = 0x10; p->cmap_regs->d2 = 0; - p->cmap_regs->addr = 0x11; p->cmap_regs->d2 = 0; + STORE_D2(0x20, init->radacal_ctrl[cmode]); + STORE_D2(0x21, p->control_use_bank2 ? 0 : 1); + STORE_D2(0x10, 0); + STORE_D2(0x11, 0); rp = &p->control_regs->vswin; for (i = 0; i < 16; ++i, ++rp) out_le32(&rp->r, init->regs[i]); - out_le32(&p->control_regs->pitch.r, init->pitch[cmode]); + out_le32(&p->control_regs->pitch.r, init->hres << cmode); out_le32(&p->control_regs->mode.r, init->mode[cmode]); out_le32(&p->control_regs->flags.r, flags); - out_le32(&p->control_regs->start_addr.r, 0); + out_le32(&p->control_regs->start_addr.r, + par->yoffset * (par->vxres << par->cmode)); out_le32(&p->control_regs->reg18.r, 0x1e5); out_le32(&p->control_regs->reg19.r, 0); @@ -556,11 +637,11 @@ static void control_set_hardware(struct fb_info_control *p) #ifdef CONFIG_FB_COMPAT_XPMAC /* And let the world know the truth. */ if (!console_fb_info || console_fb_info == &p->info) { - display_info.height = p->var.yres; - display_info.width = p->var.xres; + display_info.height = p->par.yres; + display_info.width = p->par.xres; display_info.depth = (cmode == CMODE_32) ? 32 : ((cmode == CMODE_16) ? 16 : 8); - display_info.pitch = p->fix.line_length; + display_info.pitch = p->par.vxres << p->par.cmode; display_info.mode = vmode; strncpy(display_info.name, "control", sizeof(display_info.name)); @@ -591,15 +672,6 @@ __initfunc(void control_of_init(struct device_node *dp)) unsigned long addr, size; int i, bank1, bank2; -#if 0 - if(dp->next != 0) - printk("Warning: only using first control display device.\n"); - /* danj: I have a feeling this no longer applies - if we somehow * - * had two of them, they'd be two framebuffers, right? - * Yep. - paulus - */ -#endif - if(dp->n_addrs != 2) { printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs); return; @@ -629,25 +701,23 @@ __initfunc(void control_of_init(struct device_node *dp)) /* Work out which banks of VRAM we have installed. */ /* danj: I guess the card just ignores writes to nonexistant VRAM... */ - p->frame_buffer[0] = 0x5a; - p->frame_buffer[1] = 0xc7; - bank1 = p->frame_buffer[0] == 0x5a && p->frame_buffer[1] == 0xc7; - p->frame_buffer[0x600000] = 0xa5; - p->frame_buffer[0x600001] = 0x38; - bank2 = p->frame_buffer[0x600000] == 0xa5 && p->frame_buffer[0x600001] == 0x38; + out_8(&p->frame_buffer[0], 0x5a); + out_8(&p->frame_buffer[1], 0xc7); + asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0]) : "memory" ); + bank1 = (in_8(&p->frame_buffer[0]) == 0x5a) && (in_8(&p->frame_buffer[1]) == 0xc7); + + out_8(&p->frame_buffer[0x600000], 0xa5); + out_8(&p->frame_buffer[0x600001], 0x38); + asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000]) : "memory" ); + bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xa5) + && (in_8(&p->frame_buffer[0x600001]) == 0x38); + p->total_vram = (bank1 + bank2) * 0x200000; /* If we don't have bank 1 installed, we hope we have bank 2 :-) */ p->control_use_bank2 = !bank1; if (p->control_use_bank2) p->frame_buffer += 0x600000; -#ifdef CONFIG_FB_COMPAT_XPMAC -#if 0 - console_set_cmap_ptr = control_set_cmap; - console_setmode_ptr = control_console_setmode; -#endif -#endif /* CONFIG_FB_COMPAT_XPMAC */ - init_control(p); } @@ -655,8 +725,6 @@ __initfunc(void control_of_init(struct device_node *dp)) * Get the monitor sense value. * Note that this can be called before calibrate_delay, * so we can't use udelay. - * - * Hmm - looking at platinum, should we be calling eieio() here? */ static int read_control_sense(struct fb_info_control *p) { @@ -685,6 +753,7 @@ static int read_control_sense(struct fb_info_control *p) return sense; } +/*********************** Various translation functions ***********************/ #if 1 /* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */ static int control_var_to_par(struct fb_var_screeninfo *var, @@ -726,59 +795,58 @@ static int control_var_to_par(struct fb_var_screeninfo *var, par->vmode = VMODE_1280_960_75; /* 1280x960, 75Hz */ else if (xres <= 1280 && yres <= 1024) par->vmode = VMODE_1280_1024_75; /* 1280x1024, 75Hz */ - else + else { + printk(KERN_ERR "Bad x/y res in var_to_par\n"); return -EINVAL; + } xres = control_reg_init[par->vmode-1]->hres; yres = control_reg_init[par->vmode-1]->vres; -/* + par->xres = xres; + par->yres = yres; + if (var->xres_virtual <= xres) par->vxres = xres; - else + else if(var->xres_virtual > xres) { + par->vxres = xres; + } else /* NotReached at present */ par->vxres = (var->xres_virtual+7) & ~7; + if (var->yres_virtual <= yres) par->vyres = yres; else par->vyres = var->yres_virtual; - par->xoffset = (var->xoffset+7) & ~7; - par->yoffset = var->yoffset; - if (par->xoffset+xres > par->vxres || par->yoffset+yres > par->vyres) - return -EINVAL; -*/ - - /* I'm too chicken to think about virtual */ - /* resolutions just yet. Bok bok. */ - - /* And I'm too chicken to even figure out what they are. Awk awk. [danj] */ - if (var->xres_virtual > xres || var->yres_virtual > yres - || var->xoffset != 0 || var->yoffset != 0) { + if (var->xoffset > 0 || var->yoffset+yres > par->vyres) { + printk(KERN_ERR "Bad offsets in var_to_par\n"); return -EINVAL; } - par->xres = xres; - par->yres = yres; - par->vxres = xres; - par->vyres = yres; - par->xoffset = 0; - par->yoffset = 0; + par->xoffset = (var->xoffset+7) & ~7; + par->yoffset = var->yoffset; + - if (bpp <= 8) + if (bpp <= 8) par->cmode = CMODE_8; else if (bpp <= 16) par->cmode = CMODE_16; else if (bpp <= 32) par->cmode = CMODE_32; - else + else { + printk(KERN_ERR "Bad bpp in var_to_par\n"); return -EINVAL; + } - if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram) + if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram) { + printk(KERN_ERR "Too much VRAM required for vmode %d cmode %d.\n", par->vmode, par->cmode); return -EINVAL; + } /* Check if we know about the wanted video mode */ init = control_reg_init[par->vmode-1]; if (init == NULL) { + printk(KERN_ERR "init is null in control_var_to_par().\n"); /* I'm not sure if control has any specific requirements -- */ /* if we have a regvals struct, we're good to go? */ return -EINVAL; @@ -812,14 +880,19 @@ static int control_var_to_par(struct fb_var_screeninfo *var, } #endif -#if 1 +/*********** Convert hardware data in par to an fb_var_screeninfo ***********/ + static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var) { + struct control_regints *rv; + + rv = (struct control_regints *) control_reg_init[par->vmode - 1]->regs; + memset(var, 0, sizeof(*var)); var->xres = control_reg_init[par->vmode - 1]->hres; var->yres = control_reg_init[par->vmode - 1]->vres; - var->xres_virtual = var->xres; - var->yres_virtual = var->yres; /* For now. */ + var->xres_virtual = par->vxres; + var->yres_virtual = par->vyres; var->xoffset = par->xoffset; var->yoffset = par->yoffset; var->grayscale = 0; @@ -873,12 +946,30 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni var->width = -1; var->vmode = FB_VMODE_NONINTERLACED; - /* these are total guesses, copied right out of atyfb.c */ - var->left_margin = var->right_margin = 64; - var->upper_margin = var->lower_margin = 32; - var->hsync_len = /*64*/8; - var->vsync_len = /*2*/8; - var->sync = 0; + var->left_margin = (rv->heblank - rv->hesync) + << ((par->vmode > 18) ? 2 : 1); + var->right_margin = (rv->hssync - rv->hsblank) + << ((par->vmode > 18) ? 2 : 1); + var->hsync_len = (rv->hperiod + 2 - rv->hssync + rv->hesync) + << ((par->vmode > 18) ? 2 : 1); + + var->upper_margin = (rv->veblank - rv->vesync) >> 1; + var->lower_margin = (rv->vssync - rv->vsblank) >> 1; + var->vsync_len = (rv->vperiod - rv->vssync + rv->vesync) >> 1; + + /* Acording to macmodes.c... */ + if((par->vmode >= 9 && par->vmode <= 12) || + (par->vmode >= 16 && par->vmode <= 18) || + (par->vmode == 20)) + { + var->sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT; + } else { + var->sync = 0; /* I suppose */ + } + + /* The reason these are both here: with my revised margin calculations, */ + /* these SHOULD both give the same answer for each mode. Some day I */ + /* will sit down and check the rest. Works perfectly for vmode 13. */ #if 0 /* jonh's pixclocks...*/ @@ -899,14 +990,9 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni var->pixclock >>= control_reg_init[par->vmode-1]->clock_params[2]; #endif } -#else -static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var) -{ - mac_vmode_to_var(par->vmode, par->cmode, var); -} -#endif -static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p) +static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, + struct fb_info_control *p) { memset(fix, 0, sizeof(*fix)); strcpy(fix->id, "control"); @@ -914,34 +1000,35 @@ static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_contr fix->mmio_len = sizeof(struct control_regs); fix->type = FB_TYPE_PACKED_PIXELS; + fix->ypanstep = 1; /* fix->type_aux = 0; fix->ywrapstep = 0; fix->ypanstep = 0; fix->xpanstep = 0; */ -} -/* Fix must already be inited ^^^^^^^ */ -static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, - struct fb_info_control *p) -{ fix->smem_start = (void *)(p->frame_buffer_phys + control_reg_init[par->vmode-1]->offset[par->cmode]); - p->fix.smem_len = control_vram_reqd(par->vmode, par->cmode); - /* Hmm, jonh used total_vram here. */ - p->fix.visual = (par->cmode == CMODE_8) ? + fix->smem_len = p->total_vram; + fix->visual = (par->cmode == CMODE_8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; - p->fix.line_length = par->vxres << par->cmode; - /* ywrapstep, xpanstep, ypanstep */ + fix->line_length = par->vxres << par->cmode; } -static void control_init_display(struct display *disp) +/* We never initialize any display except for p->disp. + And p->disp is already memset to 0. So no memset here. + [Found by Takashi Oe] +*/ +static void control_par_to_display(struct fb_par_control *par, + struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p) { - memset(disp, 0, sizeof(*disp)); - disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS; + /* memset(disp, 0, sizeof(*disp)); */ + disp->type = fix->type; disp->can_soft_blank = 1; - disp->scrollmode = SCROLL_YREDRAW; + disp->scrollmode = SCROLL_YNOMOVE | SCROLL_YNOPARTIAL; + disp->ypanstep = fix->ypanstep; + disp->ywrapstep = fix->ywrapstep; #if 0 disp->type_aux = fix->type_aux; disp->cmap.red = NULL; /* ??? danj */ @@ -950,22 +1037,18 @@ static void control_init_display(struct display *disp) disp->cmap.transp = NULL; /* Yeah, I realize I just set 0 = 0. */ #endif -} -static void control_par_to_display(struct fb_par_control *par, - struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p) -{ - disp->var = p->var; + control_par_to_var(par, &disp->var); disp->screen_base = (char *) p->frame_buffer + control_reg_init[par->vmode-1]->offset[par->cmode]; disp->visual = fix->visual; disp->line_length = fix->line_length; - -if(disp->scrollmode != SCROLL_YREDRAW) { - printk(KERN_ERR "Scroll mode not YREDRAW in control_par_to_display!!\n"); - disp->scrollmode = SCROLL_YREDRAW; + control_set_dispsw(disp, par->cmode, p); } - switch (par->cmode) { + +static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p) +{ + switch (cmode) { #ifdef FBCON_HAS_CFB8 case CMODE_8: disp->dispsw = &fbcon_cfb8; @@ -991,10 +1074,10 @@ if(disp->scrollmode != SCROLL_YREDRAW) { static void control_init_info(struct fb_info *info, struct fb_info_control *p) { - strcpy(info->modename, p->fix.id); + strcpy(info->modename, "control"); info->node = -1; /* ??? danj */ info->fbops = &controlfb_ops; - info->disp = &p->disp; + info->disp = &p->display; strcpy(info->fontname, fontname); info->changevar = NULL; info->switch_con = &controlfb_switch; @@ -1002,28 +1085,8 @@ static void control_init_info(struct fb_info *info, struct fb_info_control *p) info->blank = &controlfb_blank; } -/* danj: Oh, I HOPE I didn't miss anything major in here... */ -static void control_par_to_all(struct fb_info_control *p, int init) -{ - if(init) { - control_init_fix(&p->fix, p); - } - control_par_to_fix(&p->par, &p->fix, p); - - control_par_to_var(&p->par, &p->var); - - if(init) { - control_init_display(&p->disp); - } - control_par_to_display(&p->par, &p->disp, &p->fix, p); - - if(init) { - control_init_info(&p->info, p); - } -} - /* Parse user speficied options (`video=controlfb:') */ -__initfunc(void controlfb_setup(char *options, int *ints)) +__initfunc(void control_setup(char *options, int *ints)) { char *this_opt; @@ -1050,6 +1113,11 @@ __initfunc(void controlfb_setup(char *options, int *ints)) } else if (!strncmp(this_opt, "cmode:", 6)) { int depth = simple_strtoul(this_opt+6, NULL, 0); switch (depth) { + case CMODE_8: + case CMODE_16: + case CMODE_32: + default_cmode = depth; + break; case 8: default_cmode = CMODE_8; break; @@ -1081,4 +1149,5 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, return 0; } + #endif diff --git a/drivers/video/controlfb.h b/drivers/video/controlfb.h index 32943ed274dd..ea8c361057ad 100644 --- a/drivers/video/controlfb.h +++ b/drivers/video/controlfb.h @@ -73,6 +73,28 @@ struct control_regs { struct preg res[6]; }; +struct control_regints { + /* Vertical parameters are in units of 1/2 scan line */ + unsigned vswin; /* between vsblank and vssync */ + unsigned vsblank; /* vert start blank */ + unsigned veblank; /* vert end blank (display start) */ + unsigned vewin; /* between vesync and veblank */ + unsigned vesync; /* vert end sync */ + unsigned vssync; /* vert start sync */ + unsigned vperiod; /* vert period */ + unsigned reg8; + /* Horizontal params are in units of 2 pixels */ + /* Except, apparently, for hres > 1024 (or == 1280?) */ + unsigned hperiod; /* horiz period - 2 */ + unsigned hsblank; /* horiz start blank */ + unsigned heblank; /* horiz end blank */ + unsigned hesync; /* horiz end sync */ + unsigned hssync; /* horiz start sync */ + unsigned rege; + unsigned regf; + unsigned reg10; +}; + /* * Register initialization tables for the control display. * @@ -81,9 +103,10 @@ struct control_regs { * * The values for vertical frequency (V) in the comments below * are the values measured using the modes under MacOS. + * + * Pitch is always the same as bytes per line (for these video modes at least). */ struct control_regvals { - int pitch[3]; /* bytes/line, indexed by color_mode */ int offset[3]; /* first pixel address */ unsigned regs[16]; /* for vswin .. reg10 */ unsigned char mode[3]; /* indexed by color_mode */ @@ -95,7 +118,6 @@ struct control_regvals { /* Register values for 1280x1024, 75Hz mode (20) */ static struct control_regvals control_reg_init_20 = { - { 1280, 2560, 0 }, { 0x10, 0x20, 0 }, { 2129, 2128, 80, 42, 4, 2130, 2132, 88, 420, 411, 91, 35, 421, 18, 211, 386, }, @@ -107,7 +129,6 @@ static struct control_regvals control_reg_init_20 = { /* Register values for 1280x960, 75Hz mode (19) */ static struct control_regvals control_reg_init_19 = { - { 1280, 2560, 0 }, { 0x10, 0x20, 0 }, { 1997, 1996, 76, 40, 4, 1998, 2000, 86, 418, 409, 89, 35, 419, 18, 210, 384, }, @@ -119,7 +140,6 @@ static struct control_regvals control_reg_init_19 = { /* Register values for 1152x870, 75Hz mode (18) */ static struct control_regvals control_reg_init_18 = { - { 1152, 2304, 4608 }, { 0x10, 0x28, 0x50 }, { 1825, 1822, 82, 43, 4, 1828, 1830, 120, 726, 705, 129, 63, 727, 32, 364, 664 }, @@ -131,7 +151,6 @@ static struct control_regvals control_reg_init_18 = { /* Register values for 1024x768, 75Hz mode (17) */ static struct control_regvals control_reg_init_17 = { - { 1024, 2048, 4096 }, { 0x10, 0x28, 0x50 }, { 1603, 1600, 64, 34, 4, 1606, 1608, 120, 662, 641, 129, 47, 663, 24, 332, 616 }, @@ -141,9 +160,8 @@ static struct control_regvals control_reg_init_17 = { 1024, 768 }; -/* Register values for 1024x768, 72Hz mode (16 (15?)) */ -static struct control_regvals control_reg_init_16 = { - { 1024, 2048, 4096 }, +/* Register values for 1024x768, 72Hz mode 16 (15?) */ +static struct control_regvals control_reg_init_15 = { { 0x10, 0x28, 0x50 }, { 1607, 1604, 68, 39, 10, 1610, 1612, 132, 670, 653, 141, 67, 671, 34, 336, 604, }, @@ -155,7 +173,6 @@ static struct control_regvals control_reg_init_16 = { /* Register values for 1024x768, 60Hz mode (14) */ static struct control_regvals control_reg_init_14 = { - { 1024, 2048, 4096 }, { 0x10, 0x28, 0x50 }, { 1607, 1604, 68, 39, 10, 1610, 1612, 132, 670, 653, 141, 67, 671, 34, 336, 604, }, @@ -167,7 +184,6 @@ static struct control_regvals control_reg_init_14 = { /* Register values for 832x624, 75Hz mode (13) */ static struct control_regvals control_reg_init_13 = { - { 832, 1664, 3328 }, { 0x10, 0x28, 0x50 }, { 1331, 1330, 82, 43, 4, 1332, 1334, 128, 574, 553, 137, 31, 575, 16, 288, 544 }, @@ -178,7 +194,6 @@ static struct control_regvals control_reg_init_13 = { /* Register values for 800x600, 75Hz mode (12) */ static struct control_regvals control_reg_init_12 = { - { 800, 1600, 3200 }, { 0x10, 0x28, 0x50 }, { 1247, 1246, 46, 25, 4, 1248, 1250, 104, 526, 513, 113, 39, 527, 20, 264, 488, }, @@ -189,7 +204,6 @@ static struct control_regvals control_reg_init_12 = { /* Register values for 800x600, 72Hz mode (11) */ static struct control_regvals control_reg_init_11 = { - { 800, 1600, 3200 }, { 0x10, 0x28, 0x50 }, { 1293, 1256, 56, 33, 10, 1330, 1332, 76, 518, 485, 85, 59, 519, 30, 260, 460, }, @@ -200,7 +214,6 @@ static struct control_regvals control_reg_init_11 = { /* Register values for 800x600, 60Hz mode (10) */ static struct control_regvals control_reg_init_10 = { - { 800, 1600, 3200 }, { 0x10, 0x28, 0x50 }, { 1293, 1256, 56, 33, 10, 1330, 1332, 76, 518, 485, 85, 59, 519, 30, 260, 460, }, @@ -211,7 +224,6 @@ static struct control_regvals control_reg_init_10 = { /* Register values for 640x870, 75Hz Full Page Display (7) */ static struct control_regvals control_reg_init_7 = { - { 640, 1280, 2560 }, { 0x10, 0x30, 0x68 }, { 0x727, 0x724, 0x58, 0x2e, 0x4, 0x72a, 0x72c, 0x40, 0x19e, 0x18c, 0x4c, 0x27, 0x19f, 0x14, 0xd0, 0x178 }, @@ -222,7 +234,6 @@ static struct control_regvals control_reg_init_7 = { /* Register values for 640x480, 67Hz mode (6) */ static struct control_regvals control_reg_init_6 = { - { 640, 1280, 2560 }, { 0, 8, 0x10 }, { 1045, 1042, 82, 43, 4, 1048, 1050, 72, 430, 393, 73, 31, 431, 16, 216, 400 }, @@ -233,7 +244,6 @@ static struct control_regvals control_reg_init_6 = { /* Register values for 640x480, 60Hz mode (5) */ static struct control_regvals control_reg_init_5 = { - { 640, 1280, 2560 }, { 0x10, 0x28, 0x50 }, { 1037, 1026, 66, 34, 2, 1048, 1050, 56, 398, 385, 65, 47, 399, 24, 200, 352, }, @@ -253,8 +263,8 @@ static struct control_regvals *control_reg_init[VMODE_MAX] = { &control_reg_init_12, &control_reg_init_13, &control_reg_init_14, - &control_reg_init_16, - &control_reg_init_16, + &control_reg_init_15, + &control_reg_init_15, &control_reg_init_17, &control_reg_init_18, &control_reg_init_19, diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c index 6c8f14b1db99..be477a33dcab 100644 --- a/drivers/video/creatorfb.c +++ b/drivers/video/creatorfb.c @@ -1,4 +1,4 @@ -/* $Id: creatorfb.c,v 1.15 1998/09/04 15:43:40 jj Exp $ +/* $Id: creatorfb.c,v 1.16 1998/12/21 05:14:39 davem Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -123,7 +123,12 @@ #define FFB_ROP_NEW 0x83 #define FFB_UCSR_FIFO_MASK 0x00000fff +#define FFB_UCSR_FB_BUSY 0x01000000 #define FFB_UCSR_RP_BUSY 0x02000000 +#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY) +#define FFB_UCSR_READ_ERR 0x40000000 +#define FFB_UCSR_FIFO_OVFL 0x80000000 +#define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL) struct ffb_fbc { /* Next vertex registers */ @@ -271,6 +276,30 @@ struct ffb_fbc { volatile u32 mer; }; +static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n) +{ + int limit = 10000; + + do { + if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4)) + break; + if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0) + ffb->ucsr = FFB_UCSR_ALL_ERRORS; + } while(--limit > 0); +} + +static __inline__ void FFBWait(struct ffb_fbc *ffb) +{ + int limit = 10000; + + do { + if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0) + break; + if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0) + ffb->ucsr = FFB_UCSR_ALL_ERRORS; + } while(--limit > 0); +} + struct ffb_dac { volatile u32 type; volatile u32 value; @@ -313,6 +342,7 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx, register struct ffb_fbc *fbc = fb->s.ffb.fbc; int x, y, w, h; + FFBFifo(fbc, 6); fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)]; fbc->drawop = FFB_DRAWOP_RECTANGLE; @@ -330,6 +360,7 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx, fbc->bx = x + fb->x_margin; fbc->bh = h; fbc->bw = w; + FFBWait(fbc); } static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -337,15 +368,18 @@ static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s, { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + FFBFifo(fbc, 2); fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)]; fbc->drawop = FFB_DRAWOP_RECTANGLE; while (count-- > 0) { + FFBFifo(fbc, 4); fbc->by = boxes[1]; fbc->bx = boxes[0]; fbc->bh = boxes[3] - boxes[1]; fbc->bw = boxes[2] - boxes[0]; boxes += 4; } + FFBWait(fbc); } static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) @@ -370,11 +404,13 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin; else xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin; + FFBFifo(fbc, 5); fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)]; fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)]; fbc->fontw = fontwidth(p); fbc->fontinc = 0x10000; fbc->fontxy = xy; + FFBFifo(fbc, fontheight(p)); if (fontwidth(p) <= 8) { for (i = 0; i < fontheight(p); i++) fbc->font = *fd++ << 24; @@ -384,6 +420,7 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int fd += 2; } } + FFBWait(fbc); } static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -394,6 +431,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh int i, xy; u8 *fd1, *fd2, *fd3, *fd4; + FFBFifo(fbc, 2); fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)]; fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)]; xy = fb->s.ffb.xy_margin; @@ -408,6 +446,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh if (fontwidth(p) <= 8) { while (count >= 4) { count -= 4; + FFBFifo(fbc, 3); fbc->fontw = 4 * fontwidth(p); fbc->fontinc = 0x10000; fbc->fontxy = xy; @@ -422,6 +461,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); } + FFBFifo(fbc, fontheight(p)); if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++) fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) @@ -437,6 +477,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh } else { while (count >= 2) { count -= 2; + FFBFifo(fbc, 3); fbc->fontw = 2 * fontwidth(p); fbc->fontinc = 0x10000; fbc->fontxy = xy; @@ -447,6 +488,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); } + FFBFifo(fbc, fontheight(p)); for (i = 0; i < fontheight(p); i++) { fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); fd1 += 2; fd2 += 2; @@ -456,6 +498,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh } while (count) { count--; + FFBFifo(fbc, 3); fbc->fontw = fontwidth(p); fbc->fontinc = 0x10000; fbc->fontxy = xy; @@ -463,6 +506,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh i = ((*s++ & p->charmask) << fontheightlog(p)); else i = ((*s++ & p->charmask) * fontheight(p)); + FFBFifo(fbc, fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++) @@ -476,6 +520,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh } xy += fontwidth(p); } + FFBWait(fbc); } static void ffb_revc(struct display *p, int xx, int yy) @@ -573,10 +618,12 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + FFBFifo(fbc, 4); fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST; fbc->fbc = 0x2000707f; fbc->rop = FFB_ROP_NEW; fbc->pmask = 0xffffffff; + FFBWait(fbc); } static char idstring[60] __initdata = { 0 }; @@ -625,6 +672,12 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) fb->switch_from_graph = ffb_switch_from_graph; fb->fill = ffb_fill; + /* If there are any read errors or fifo overflow conditions, + * clear them now. + */ + if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0) + fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS; + ffb_switch_from_graph(fb); fb->physbase = regs[0].phys_addr; diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index 80ec1481be89..67034a9a9df7 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -166,6 +166,8 @@ static unsigned char Cyber_colour_table [256][3]; static unsigned long CyberMem; static unsigned long CyberSize; static volatile char *CyberRegs; +static unsigned long CyberMem_phys; +static unsigned long CyberRegs_phys; /* From cvision.c for cvision_core.c */ static unsigned long cv64_mem; static unsigned long cv64_fbmem; @@ -428,9 +430,9 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, DPRINTK("ENTER\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, cyberfb_name); - fix->smem_start = (char*) virt_to_phys ((void *)CyberMem); + fix->smem_start = (char*) CyberMem_phys; fix->smem_len = CyberSize; - fix->mmio_start = (char*) virt_to_phys ((void *)CyberRegs); + fix->mmio_start = (char*) CyberRegs_phys; fix->mmio_len = 0x10000; fix->type = FB_TYPE_PACKED_PIXELS; @@ -1153,6 +1155,8 @@ __initfunc(void cyberfb_init(void)) CyberMem = cv64_fbmem; CyberRegs = cv64_regs; + CyberMem_phys = board_addr + 0x01400000; + CyberRegs_phys = CyberMem_phys + 0x00c00000; DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem, (long unsigned int)CyberRegs); @@ -1453,7 +1457,7 @@ unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */ /* -------------------- Hardware specific routines ------------------------- */ #if 0 /* ARB Generates 100 usec delay */ -inline void __delay (unsigned long usecs) +inline void __cv_delay (unsigned long usecs) { int k; @@ -1493,7 +1497,7 @@ inline unsigned char RAttr (volatile caddr_t board, short idx) { vgaw (board, ACT_ADDRESS_W, idx); udelay(100); - /* __delay (0); */ + /* __cv_delay (0); */ return (vgar (board, ACT_ADDRESS_R)); } @@ -1895,7 +1899,7 @@ static void cv64_board_init (void) vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x07); vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x1000); udelay(200); - /* __delay (200000); */ + /* __cv_delay (200000); */ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x2000); Cyber_WaitBlit(); /* GfxBusyWait (cv64_regs); */ @@ -1903,7 +1907,7 @@ static void cv64_board_init (void) Cyber_WaitBlit(); /* GfxBusyWait (cv64_regs); */ udelay(200); - /* __delay (200000); */ + /* __cv_delay (200000); */ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF); Cyber_WaitBlit(); /* GfxBusyWait (cv64_regs); */ @@ -1961,7 +1965,9 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) int xres, hfront, hsync, hback; int yres, vfront, vsync, vback; int bpp; +#if 0 float freq_f; +#endif long freq; /* ---------------- */ @@ -2066,9 +2072,15 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) /* cv64_compute_clock accepts arguments in Hz */ /* pixclock is in ps ... convert to Hz */ +#if 0 freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000; freq = ((long) freq_f) * 1000; - +#else +/* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock); + */ + freq = (1000000000 / video_mode->pixclock) * 1000; +#endif + mnr = cv64_compute_clock (freq); WSeq (cv64_regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8)); WSeq (cv64_regs, SEQ_ID_DCLK_LO, (mnr & 0xFF)); @@ -2257,14 +2269,14 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_1, cr50); udelay(100); - /* __delay (100000); */ + /* __cv_delay (100000); */ WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41)); udelay(100); - /* __delay (100000); */ + /* __cv_delay (100000); */ WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA, (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F); udelay(100); - /* __delay (100000); */ + /* __cv_delay (100000); */ tfillm = (96 * (cv64_memclk / 1000)) / 240000; @@ -2296,7 +2308,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, m); WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, n); udelay(10); - /* __delay (10000); */ + /* __cv_delay (10000); */ /* Text initialization */ diff --git a/drivers/video/cyberfb.h b/drivers/video/cyberfb.h index 232bc685723c..bce02a462d05 100644 --- a/drivers/video/cyberfb.h +++ b/drivers/video/cyberfb.h @@ -421,7 +421,7 @@ do { \ /* --------------------------------- */ /* in cvision_core.c */ -inline void __delay(unsigned long usecs); +inline void __cv_delay(unsigned long usecs); inline void GfxBusyWait(volatile caddr_t board); inline void GfxFifoWait(volatile caddr_t board); inline unsigned char RAttr(volatile caddr_t board, short idx); diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c index 5fe78bc30e0a..bfa98c71948f 100644 --- a/drivers/video/fbcon-cfb8.c +++ b/drivers/video/fbcon-cfb8.c @@ -143,12 +143,12 @@ void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, case 12: case 16: for (rows = fontheight(p) ; rows-- ; dest += bytes) { - ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx; - ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx; - ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[2]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; if (fontwidth(p) == 16) ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx; - cdat += 2; + cdat++; } break; } @@ -200,12 +200,12 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, cdat = p->fontdata + (c * fontheight(p) << 1); for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { - ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx; - ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx; - ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[2]= (nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx; if (fontwidth(p) == 16) ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx; - cdat += 2; + cdat++; } dest0+=fontwidth(p); } diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 9bdc9020b0f9..657bbdb136a6 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -944,7 +944,8 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, { int unit = conp->vc_num; struct display *p = &fb_display[unit]; - int is_txt = (p->type == FB_TYPE_TEXT); + int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); + int logos_left = 0; int logos_width = conp->vc_cols; if (!p->can_soft_blank && console_blanked) return 0; @@ -962,22 +963,34 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, switch (dir) { case SM_UP: + /* K.Garloff@ping.de, 98/10/21: If logo is diplayed, only save logo + * and not the hole top region. In combination with the logo being + * displayed on the right side, this allows scrollback feature + * when bootlogo is displayed. */ + if (t != 0 && logo_shown == fg_console) { + struct display *p = &fb_display[unit]; + int lw = (smp_num_cpus * (LOGO_W + 8) - 7) / fontwidth(p) + 1; + logos_left = conp->vc_cols - lw; + while (logos_left < 0) logos_left += (LOGO_W + 8 - 7) / fontwidth(p); + logos_width = conp->vc_cols - logos_left; + } if (count > conp->vc_rows) /* Maximum realistic size */ count = conp->vc_rows; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: - p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count, + if (t > 0) p->dispsw->bmove(p, 0, logos_left, count, + logos_left, t, logos_width); + p->dispsw->bmove(p, count, 0, 0, 0, b-count, conp->vc_cols); - p->dispsw->clear(conp, p, b-count, 0, count, + p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YWRAP: - if (b-t-count > 3*conp->vc_rows>>2) { + if (b-t-count > 2*conp->vc_rows/3) { if (t > 0) - fbcon_bmove(conp, 0, 0, count, 0, t, - conp->vc_cols); - ywrap_up(unit, conp, p, count); + fbcon_bmove(conp, 0, logos_left, count, logos_left, t, logos_width); + ywrap_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); @@ -990,11 +1003,11 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, break; case __SCROLL_YPAN: - if (( is_txt && (b-t == conp->vc_rows)) || - (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) { + if (( !scroll_partial && (b-t == conp->vc_rows)) || + ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) { if (t > 0) - fbcon_bmove(conp, 0, 0, count, 0, t, - conp->vc_cols); + fbcon_bmove(conp, 0, logos_left, count, logos_left, t, + logos_width); ypan_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, @@ -1049,8 +1062,8 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, break; case __SCROLL_YPAN: - if (( is_txt && (b-t == conp->vc_rows)) || - (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) { + if (( !scroll_partial && (b-t == conp->vc_rows)) || + ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) { if (conp->vc_rows-b > 0) fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b, conp->vc_cols); @@ -1250,46 +1263,41 @@ static inline int fbcon_get_font(int unit, struct console_font_op *op) if (!op->data) return 0; if (op->width <= 8) { + j = fontheight(p); for (i = 0; i < op->charcount; i++) { - for (j = 0; j < fontheight(p); j++) - *data++ = *fontdata++; - memset(data, 0, 32-j); - data += 32 - j; + memcpy(data, fontdata, j); + memset(data+j, 0, 32-j); + data += 32; + fontdata += j; } } #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY else if (op->width <= 16) { + j = fontheight(p) * 2; for (i = 0; i < op->charcount; i++) { - for (j = 0; j < fontheight(p); j++) { - *data++ = *(u16 *)fontdata >> 8; - *data++ = *(u16 *)fontdata; - fontdata += sizeof(u16); - } - memset(data, 0, 2*(32-j)); - data += 2 * (32 - j); + memcpy(data, fontdata, j); + memset(data+j, 0, 64-j); + data += 64; + fontdata += j; } } else if (op->width <= 24) { for (i = 0; i < op->charcount; i++) { for (j = 0; j < fontheight(p); j++) { - *data++ = *(u32 *)fontdata >> 24; - *data++ = *(u32 *)fontdata >> 16; - *data++ = *(u32 *)fontdata >> 8; + *data++ = fontdata[0]; + *data++ = fontdata[1]; + *data++ = fontdata[2]; fontdata += sizeof(u32); } memset(data, 0, 3*(32-j)); data += 3 * (32 - j); } } else { + j = fontheight(p) * 4; for (i = 0; i < op->charcount; i++) { - for (j = 0; j < fontheight(p); j++) { - *data++ = *(u32 *)fontdata >> 24; - *data++ = *(u32 *)fontdata >> 16; - *data++ = *(u32 *)fontdata >> 8; - *data++ = *(u32 *)fontdata; - fontdata += sizeof(u32); - } - memset(data, 0, 4*(32-j)); - data += 4 * (32 - j); + memcpy(data, fontdata, j); + memset(data+j, 0, 128-j); + data += 128; + fontdata += j; } } #endif @@ -1329,12 +1337,44 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int p->fgshift--; p->bgshift--; p->charmask = 0xff; + + /* ++Edmund: reorder the attribute bits */ + { + struct vc_data *conp = p->conp; + unsigned short *cp = (unsigned short *) conp->vc_origin; + int count = conp->vc_screenbuf_size/2; + unsigned short c; + for (; count > 0; count--, cp++) { + c = scr_readw(cp); + scr_writew(((c & 0xfe00) >> 1) | (c & 0xff), cp); + } + c = conp->vc_video_erase_char; + conp->vc_video_erase_char = ((c & 0xfe00) >> 1) | (c & 0xff); + conp->vc_attr >>= 1; + } + } else if (!p->conp->vc_hi_font_mask && cnt == 512) { p->conp->vc_hi_font_mask = 0x100; p->conp->vc_complement_mask <<= 1; p->fgshift++; p->bgshift++; p->charmask = 0x1ff; + + /* ++Edmund: reorder the attribute bits */ + { + struct vc_data *conp = p->conp; + unsigned short *cp = (unsigned short *) conp->vc_origin; + int count = conp->vc_screenbuf_size/2; + unsigned short c; + for (; count > 0; count--, cp++) { + c = scr_readw(cp); + scr_writew(((c & 0xff00) << 1) | (c & 0xff), cp); + } + c = conp->vc_video_erase_char; + conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff); + conp->vc_attr <<= 1; + } + } fbcon_font_widths(p); @@ -1381,16 +1421,13 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op) int h = op->height; int size = h; int i, j, k; - u8 *new_data, *data = op->data, c, *p; -#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY - u32 d; -#else + u8 *new_data, *data = op->data, *p; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY if (w != 8) return -EINVAL; #endif - - if (w > 32 || (op->charcount != 256 && op->charcount != 512)) + if ((w <= 0) || (w > 32) || (op->charcount != 256 && op->charcount != 512)) return -EINVAL; if (w > 8) { @@ -1407,56 +1444,46 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op) FNTSIZE(new_data) = size; FNTCHARCNT(new_data) = op->charcount; REFCOUNT(new_data) = 0; /* usage counter */ - k = 0; p = new_data; if (w <= 8) { for (i = 0; i < op->charcount; i++) { - for (j = 0; j < h; j++) { - c = *data++; - k += c; - *p++ = c; - } - data += 32 - h; + memcpy(p, data, h); + data += 32; + p += h; } } #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY else if (w <= 16) { + h *= 2; for (i = 0; i < op->charcount; i++) { - for (j = 0; j < h; j++) { - d = (data[0] << 8) | data[1]; - data += 2; - k += d; - *(u16 *)p = d; - p += sizeof(u16); - } - data += 2*(32 - h); + memcpy(p, data, h); + data += 64; + p += h; } - } else { + } else if (w <= 24) { for (i = 0; i < op->charcount; i++) { for (j = 0; j < h; j++) { - if (w <= 24) { - d = (data[0] << 24) | - (data[1] << 16) | - (data[2] << 8); - data += 3; - } else { - d = (data[0] << 24) | - (data[1] << 16) | - (data[2] << 8) | - data[3]; - data += 4; - } - k += d; - *(u32 *)p = d; + memcpy(p, data, 3); + p[3] = 0; + data += 3; p += sizeof(u32); } - if (w <= 24) - data += 3*(32 - h); - else - data += 4*(32 - h); + data += 3*(32 - h); + } + } else { + h *= 4; + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, h); + data += 128; + p += h; } } #endif + /* we can do it in u32 chunks because of charcount is 256 or 512, so + font length must be multiple of 256, at least. And 256 is multiple + of 4 */ + k = 0; + while (p > new_data) k += *--(u32 *)p; FNTSUM(new_data) = k; /* Check if the same font is on some other console already */ for (i = 0; i < MAX_NR_CONSOLES; i++) { @@ -1587,7 +1614,7 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines) p->var.xoffset = 0; p->var.yoffset = offset*fontheight(p); p->fb_info->updatevar(unit, p->fb_info); - if (!offset) + if (!scrollback_current) fbcon_cursor(conp, CM_DRAW); return 0; } @@ -1664,8 +1691,8 @@ __initfunc(static int fbcon_show_logo( void )) logo_depth = 1; } - for (x = 0; x < smp_num_cpus * (LOGO_W + 8) && - x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) { + for (x = p->var.xres - LOGO_W; x > 0 && x > (int)p->var.xres + - smp_num_cpus * (LOGO_W + 8); x -= (LOGO_W + 8)) { #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) @@ -1768,6 +1795,20 @@ __initfunc(static int fbcon_show_logo( void )) done = 1; } #endif +#if defined(CONFIG_FBCON_CFB4) + if (depth == 4 && p->type == FB_TYPE_PACKED_PIXELS) { + src = logo; + for( y1 = 0; y1 < LOGO_H; y1++) { + dst = fb + y1*line + x/2; + for( x1 = 0; x1 < LOGO_W/2; x1++) { + u8 q = *src++; + q = (q << 4) | (q >> 4); + *dst++ = q; + } + } + done = 1; + } +#endif #if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FB_SBUS) if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) { /* depth 8 or more, packed, with color registers */ diff --git a/drivers/video/font_sun12x22.c b/drivers/video/font_sun12x22.c index c4cd54c7a486..803b35ea8d72 100644 --- a/drivers/video/font_sun12x22.c +++ b/drivers/video/font_sun12x22.c @@ -1,6207 +1,6207 @@ #include