diff -urN oldtree/Documentation/fb/00-INDEX newtree/Documentation/fb/00-INDEX --- oldtree/Documentation/fb/00-INDEX 2006-01-03 03:21:10.000000000 +0000 +++ newtree/Documentation/fb/00-INDEX 2006-02-18 15:29:54.291728400 +0000 @@ -19,6 +19,8 @@ - info on the Matrox frame buffer driver pvr2fb.txt - info on the PowerVR 2 frame buffer driver +splash.txt + - info on the Framebuffer Splash tgafb.txt - info on the TGA (DECChip 21030) frame buffer driver vesafb.txt diff -urN oldtree/Documentation/fb/splash.txt newtree/Documentation/fb/splash.txt --- oldtree/Documentation/fb/splash.txt 1970-01-01 00:00:00.000000000 +0000 +++ newtree/Documentation/fb/splash.txt 2006-02-18 15:29:54.293728096 +0000 @@ -0,0 +1,207 @@ +What is it? +----------- + +The framebuffer splash is a kernel feature that allows displaying a background +picture on selected consoles. + +What do I need to get it to work? +--------------------------------- + +To get fb splash up-and-running you will have to: + 1) get a copy of splashutils [1] or a similar program + 2) get some splash themes + 3) build the kernel helper program + 4) build your kernel with the FB_SPLASH option enabled. + +To get fb splash operational right after fbcon initialization is finished, you +will have to include a theme and the kernel helper into your initramfs image. +Please refer to splashutils documentation for instructions on how to do that. + +[1] The splashutils package can be downloaded from: + http://dev.gentoo.org/~spock/projects/splashutils/ + +The userspace helper +-------------------- + +The userspace splash helper (by default: /sbin/splash_helper) is called by the +kernel whenever an important event occurs and the kernel needs some kind of +job to be carried out. Important events include console switches and graphic +mode switches (the kernel requests background images and configuration +parameters for the current console). The splash helper must be accessible at +all times. If it's not, fbsplash will be switched off automatically. + +It's possible to set path to the splash helper by writing it to +/proc/sys/kernel/fbsplash. + +***************************************************************************** + +The information below is mostly technical stuff. There's probably no need to +read it unless you plan to develop a userspace helper. + +The splash protocol +------------------- + +The splash protocol defines a communication interface between the kernel and +the userspace splash helper. + +The kernel side is responsible for: + + o rendering console text, using an image as a background (instead of a + standard solid color fbcon uses), + o accepting commands from the user via ioctls on the fbsplash device, + o calling the userspace helper to set things up as soon as the fb subsystem + is initialized. + +The userspace helper is responsible for everything else, including parsing +configuration files, decompressing the image files whenever the kernel needs +it, and communicating with the kernel if necessary. + +The splash protocol specifies how communication is done in both ways: +kernel->userspace and userspace->helper. + +Kernel -> Userspace +------------------- + +The kernel communicates with the userspace helper by calling it and specifying +the task to be done in a series of arguments. + +The arguments follow the pattern: + + +All commands defined in splash protocol v2 have the following parameters: + virtual console + framebuffer number + theme + +Splash protocol v1 specified an additional 'fbsplash mode' after the +framebuffer number. Splash protocol v1 is deprecated and should not be used. + +Splash protocol v2 specifies the following commands: + +getpic +------ + The kernel issues this command to request image data. It's up to the userspace + helper to find a background image appropriate for the specified theme and the + current resolution. The userspace helper should respond by issuing the + FBIOSPLASH_SETPIC ioctl. + +init +---- + The kernel issues this command after the fbsplash device is created and + the fbsplash interface is initialized. Upon receiving 'init', the userspace + helper should parse the kernel command line (/proc/cmdline) or otherwise + decide whether fbsplash is to be activated. + + To activate fbsplash on the first console the helper should issue the + FBIOSPLASH_SETCFG, FBIOSPLASH_SETPIC and FBIOSPLASH_SETSTATE commands, + in the above-mentioned order. + + When the userspace helper is called in an early phase of the boot process + (right after the initialization of fbcon), no filesystems will be mounted. + The helper program should mount sysfs and then create the appropriate + framebuffer, fbsplash and tty0 devices (if they don't already exist) to get + current display settings and to be able to communicate with the kernel side. + It should probably also mount the procfs to be able to parse the kernel + command line parameters. + + Note that the console sem is not held when the kernel calls splash_helper + with the 'init' command. The splash helper should perform all ioctls with + origin set to FB_SPLASH_IO_ORIG_USER. + +modechange +---------- + The kernel issues this command on a mode change. The helper's response should + be similar to the response to the 'init' command. Note that this time the + console sem is held and all ioctls must be performed with origin set to + FB_SPLASH_IO_ORIG_KERNEL. + + +Userspace -> Kernel +------------------- + +Userspace programs can communicate with fbsplash via ioctls on the fbsplash +device. These ioctls are to be used by both the userspace helper (called +only by the kernel) and userspace configuration tools (run by the users). + +The splash helper should set the origin field to FB_SPLASH_IO_ORIG_KERNEL +when doing the appropriate ioctls. All userspace configuration tools should +use FB_SPLASH_IO_ORIG_USER. Failure to set the appropriate value in the origin +field when performing ioctls from the kernel helper will most likely result +in a console deadlock. + +FB_SPLASH_IO_ORIG_KERNEL instructs fbsplash not to try to acquire the console +semaphore. Not surprisingly, FB_SPLASH_IO_ORIG_USER instructs it to acquire +the console sem. + +The framebuffer splash provides the following ioctls (all defined in +linux/fb.h): + +FBIOSPLASH_SETPIC +description: loads a background picture for a virtual console +argument: struct fb_splash_iowrapper*; data: struct fb_image* +notes: +If called for consoles other than the current foreground one, the picture data +will be ignored. + +If the current virtual console is running in a 8-bpp mode, the cmap substruct +of fb_image has to be filled appropriately: start should be set to 16 (first +16 colors are reserved for fbcon), len to a value <= 240 and red, green and +blue should point to valid cmap data. The transp field is ingored. The fields +dx, dy, bg_color, fg_color in fb_image are ignored as well. + +FBIOSPLASH_SETCFG +description: sets the fbsplash config for a virtual console +argument: struct fb_splash_iowrapper*; data: struct vc_splash* +notes: The structure has to be filled with valid data. + +FBIOSPLASH_GETCFG +description: gets the fbsplash config for a virtual console +argument: struct fb_splash_iowrapper*; data: struct vc_splash* + +FBIOSPLASH_SETSTATE +description: sets the fbsplash state for a virtual console +argument: struct fb_splash_iowrapper*; data: unsigned int* + values: 0 = disabled, 1 = enabled. + +FBIOSPLASH_GETSTATE +description: gets the fbsplash state for a virtual console +argument: struct fb_splash_iowrapper*; data: unsigned int* + values: as in FBIOSPLASH_SETSTATE + +Info on used structures: + +Definition of struct vc_splash can be found in linux/console_splash.h. It's +heavily commented. Note that the 'theme' field should point to a string +no longer than FB_SPLASH_THEME_LEN. When FBIOSPLASH_GETCFG call is +performed, the theme field should point to a char buffer of length +FB_SPLASH_THEME_LEN. + +Definition of struct fb_splash_iowrapper can be found in linux/fb.h. +The fields in this struct have the following meaning: + +vc: +Virtual console number. + +origin: +Specifies if the ioctl is performed as a response to a kernel request. The +splash helper should set this field to FB_SPLASH_IO_ORIG_KERNEL, userspace +programs should set it to FB_SPLASH_IO_ORIG_USER. This field is necessary to +avoid console semaphore deadlocks. + +data: +Pointer to a data structure appropriate for the performed ioctl. Type of +the data struct is specified in the ioctls description. + +***************************************************************************** + +Credit +------ + +Original 'bootsplash' project & implementation by: + Volker Poplawski , Stefan Reinauer , + Steffen Winterfeldt , Michael Schroeder , + Ken Wimer . + +Fbsplash, splash protocol design, current implementation & docs by: + Michael Januszewski + diff -urN oldtree/drivers/Makefile newtree/drivers/Makefile --- oldtree/drivers/Makefile 2006-02-18 15:18:23.996669200 +0000 +++ newtree/drivers/Makefile 2006-02-18 15:29:54.294727944 +0000 @@ -8,6 +8,9 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ +# char/ comes before serial/ etc so that the VT console is the boot-time +# default. +obj-y += char/ obj-y += video/ obj-$(CONFIG_ACPI) += acpi/ # PnP must come after ACPI since it will eventually need to check if acpi @@ -15,10 +18,6 @@ obj-$(CONFIG_PNP) += pnp/ obj-$(CONFIG_ARM_AMBA) += amba/ -# char/ comes before serial/ etc so that the VT console is the boot-time -# default. -obj-y += char/ - obj-$(CONFIG_CONNECTOR) += connector/ # i810fb and intelfb depend on char/agp/ diff -urN oldtree/drivers/video/Kconfig newtree/drivers/video/Kconfig --- oldtree/drivers/video/Kconfig 2006-02-18 15:18:29.156884728 +0000 +++ newtree/drivers/video/Kconfig 2006-02-18 15:29:54.296727640 +0000 @@ -754,7 +754,6 @@ select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING select FB_MACMODES if PPC_PMAC ---help--- Say Y here if you have a Matrox Millennium, Matrox Millennium II, @@ -1458,5 +1457,15 @@ source "drivers/video/backlight/Kconfig" endif -endmenu +config FB_SPLASH + bool "Support for the framebuffer splash" + depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING + default n + ---help--- + This option enables support for the Linux boot-up splash screen and + graphical backgrounds on consoles. Note that you will need userspace + splash utilities in order to take advantage of these features. Refer + to Documentation/fb/splash.txt for more information. + If unsure, say N. +endmenu diff -urN oldtree/drivers/video/Kconfig.orig newtree/drivers/video/Kconfig.orig --- oldtree/drivers/video/Kconfig.orig 1970-01-01 00:00:00.000000000 +0000 +++ newtree/drivers/video/Kconfig.orig 2006-02-18 15:18:29.000000000 +0000 @@ -0,0 +1,1462 @@ +# +# Video configuration +# + +menu "Graphics support" + +config FB + tristate "Support for frame buffer devices" + ---help--- + The frame buffer device provides an abstraction for the graphics + hardware. It represents the frame buffer of some video hardware and + allows application software to access the graphics hardware through + a well-defined interface, so the software doesn't need to know + anything about the low-level (hardware register) stuff. + + Frame buffer devices work identically across the different + architectures supported by Linux and make the implementation of + application programs easier and more portable; at this point, an X + server exists which uses the frame buffer device exclusively. + On several non-X86 architectures, the frame buffer device is the + only way to use the graphics hardware. + + The device is accessed through special device nodes, usually located + in the /dev directory, i.e. /dev/fb*. + + You need an utility program called fbset to make full use of frame + buffer devices. Please read + and the Framebuffer-HOWTO at + for more + information. + + Say Y here and to the driver for your graphics board below if you + are compiling a kernel for a non-x86 architecture. + + If you are compiling for the x86 architecture, you can say Y if you + want to play with it, but it is not essential. Please note that + running graphical applications that directly touch the hardware + (e.g. an accelerated X server) and that are not frame buffer + device-aware may cause unexpected results. If unsure, say N. + +config FB_CFB_FILLRECT + tristate + depends on FB + default n + ---help--- + Include the cfb_fillrect function for generic software rectangle + filling. This is used by drivers that don't provide their own + (accelerated) version. + +config FB_CFB_COPYAREA + tristate + depends on FB + default n + ---help--- + Include the cfb_copyarea function for generic software area copying. + This is used by drivers that don't provide their own (accelerated) + version. + +config FB_CFB_IMAGEBLIT + tristate + depends on FB + default n + ---help--- + Include the cfb_imageblit function for generic software image + blitting. This is used by drivers that don't provide their own + (accelerated) version. + +config FB_MACMODES + tristate + depends on FB + default n + +config FB_MODE_HELPERS + bool "Enable Video Mode Handling Helpers" + depends on FB + default n + ---help--- + This enables functions for handling video modes using the + Generalized Timing Formula and the EDID parser. A few drivers rely + on this feature such as the radeonfb, rivafb, and the i810fb. If + your driver does not take advantage of this feature, choosing Y will + just increase the kernel size by about 5K. + +config FB_TILEBLITTING + bool "Enable Tile Blitting Support" + depends on FB + default n + ---help--- + This enables tile blitting. Tile blitting is a drawing technique + where the screen is divided into rectangular sections (tiles), whereas + the standard blitting divides the screen into pixels. Because the + default drawing element is a tile, drawing functions will be passed + parameters in terms of number of tiles instead of number of pixels. + For example, to draw a single character, instead of using bitmaps, + an index to an array of bitmaps will be used. To clear or move a + rectangular section of a screen, the rectangle will be described in + terms of number of tiles in the x- and y-axis. + + This is particularly important to one driver, matroxfb. If + unsure, say N. + +config FB_CIRRUS + tristate "Cirrus Logic support" + depends on FB && (ZORRO || PCI) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This enables support for Cirrus Logic GD542x/543x based boards on + Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. + + If you have a PCI-based system, this enables support for these + chips: GD-543x, GD-544x, GD-5480. + + Please read the file . + + Say N unless you have such a graphics board or plan to get one + before you next recompile the kernel. + +config FB_PM2 + tristate "Permedia2 support" + depends on FB && ((AMIGA && BROKEN) || PCI) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Permedia2 AGP frame + buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a + product page at + . + +config FB_PM2_FIFO_DISCONNECT + bool "enable FIFO disconnect feature" + depends on FB_PM2 && PCI + help + Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2). + +config FB_ARMCLCD + tristate "ARM PrimeCell PL110 support" + depends on FB && ARM && ARM_AMBA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This framebuffer device driver is for the ARM PrimeCell PL110 + Colour LCD controller. ARM PrimeCells provide the building + blocks for System on a Chip devices. + + If you want to compile this as a module (=code which can be + inserted into and removed from the running kernel), say M + here and read . The module + will be called amba-clcd. + +config FB_ACORN + bool "Acorn VIDC support" + depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Acorn VIDC graphics + hardware found in Acorn RISC PCs and other ARM-based machines. If + unsure, say N. + +config FB_CLPS711X + bool "CLPS711X LCD support" + depends on (FB = y) && ARM && ARCH_CLPS711X + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y to enable the Framebuffer driver for the CLPS7111 and + EP7212 processors. + +config FB_SA1100 + bool "SA-1100 LCD support" + depends on (FB = y) && ARM && ARCH_SA1100 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is a framebuffer device for the SA-1100 LCD Controller. + See for information on framebuffer + devices. + + If you plan to use the LCD display with your SA-1100 system, say + Y here. + +config FB_IMX + tristate "Motorola i.MX LCD support" + depends on FB && ARM && ARCH_IMX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + +config FB_CYBER2000 + tristate "CyberPro 2000/2010/5000 support" + depends on FB && PCI && (BROKEN || !SPARC64) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the Integraphics CyberPro 20x0 and 5000 + VGA chips used in the Rebel.com Netwinder and other machines. + Say Y if you have a NetWinder or a graphics card containing this + device, otherwise say N. + +config FB_APOLLO + bool + depends on (FB = y) && APOLLO + default y + select FB_CFB_FILLRECT + select FB_CFB_IMAGEBLIT + +config FB_Q40 + bool + depends on (FB = y) && Q40 + default y + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + +config FB_AMIGA + tristate "Amiga native chipset support" + depends on FB && AMIGA + help + This is the frame buffer device driver for the builtin graphics + chipset found in Amigas. + + To compile this driver as a module, choose M here: the + module will be called amifb. + +config FB_AMIGA_OCS + bool "Amiga OCS chipset support" + depends on FB_AMIGA + help + This enables support for the original Agnus and Denise video chips, + found in the Amiga 1000 and most A500's and A2000's. If you intend + to run Linux on any of these systems, say Y; otherwise say N. + +config FB_AMIGA_ECS + bool "Amiga ECS chipset support" + depends on FB_AMIGA + help + This enables support for the Enhanced Chip Set, found in later + A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If + you intend to run Linux on any of these systems, say Y; otherwise + say N. + +config FB_AMIGA_AGA + bool "Amiga AGA chipset support" + depends on FB_AMIGA + help + This enables support for the Advanced Graphics Architecture (also + known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T + and CD32. If you intend to run Linux on any of these systems, say Y; + otherwise say N. + +config FB_CYBER + tristate "Amiga CyberVision 64 support" + depends on FB && ZORRO && BROKEN + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the Cybervision 64 graphics card from + Phase5. Please note that its use is not all that intuitive (i.e. if + you have any questions, be sure to ask!). Say N unless you have a + Cybervision 64 or plan to get one before you next recompile the + kernel. Please note that this driver DOES NOT support the + Cybervision 64/3D card, as they use incompatible video chips. + +config FB_VIRGE + bool "Amiga CyberVision 64/3D support " + depends on (FB = y) && ZORRO && BROKEN + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the Cybervision 64/3D graphics card from + Phase5. Please note that its use is not all that intuitive (i.e. if + you have any questions, be sure to ask!). Say N unless you have a + Cybervision 64/3D or plan to get one before you next recompile the + kernel. Please note that this driver DOES NOT support the older + Cybervision 64 card, as they use incompatible video chips. + +config FB_RETINAZ3 + tristate "Amiga Retina Z3 support" + depends on (FB = y) && ZORRO && BROKEN + help + This enables support for the Retina Z3 graphics card. Say N unless + you have a Retina Z3 or plan to get one before you next recompile + the kernel. + +config FB_FM2 + bool "Amiga FrameMaster II/Rainbow II support" + depends on (FB = y) && ZORRO + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Amiga FrameMaster + card from BSC (exhibited 1992 but not shipped as a CBM product). + +config FB_ARC + tristate "Arc Monochrome LCD board support" + depends on FB && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the Arc Monochrome LCD board. The board + is based on the KS-108 lcd controller and is typically a matrix + of 2*n chips. This driver was tested with a 128x64 panel. This + driver supports it for use with x86 SBCs through a 16 bit GPIO + interface (8 bit data, 8 bit control). If you anticpate using + this driver, say Y or M; otherwise say N. You must specify the + GPIO IO address to be used for setting control and data. + +config FB_ATARI + bool "Atari native chipset support" + depends on (FB = y) && ATARI && BROKEN + help + This is the frame buffer device driver for the builtin graphics + chipset found in Ataris. + +config FB_OF + bool "Open Firmware frame buffer device support" + depends on (FB = y) && (PPC64 || PPC_OF) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + Say Y if you want support with Open Firmware for your graphics + board. + +config FB_CONTROL + bool "Apple \"control\" display support" + depends on (FB = y) && PPC_PMAC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + This driver supports a frame buffer for the graphics adapter in the + Power Macintosh 7300 and others. + +config FB_PLATINUM + bool "Apple \"platinum\" display support" + depends on (FB = y) && PPC_PMAC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + This driver supports a frame buffer for the "platinum" graphics + adapter in some Power Macintoshes. + +config FB_VALKYRIE + bool "Apple \"valkyrie\" display support" + depends on (FB = y) && (MAC || PPC_PMAC) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + This driver supports a frame buffer for the "valkyrie" graphics + adapter in some Power Macintoshes. + +config FB_CT65550 + bool "Chips 65550 display support" + depends on (FB = y) && PPC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Chips & Technologies + 65550 graphics chip in PowerBooks. + +config FB_ASILIANT + bool "Asiliant (Chips) 69000 display support" + depends on (FB = y) && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + +config FB_IMSTT + bool "IMS Twin Turbo display support" + depends on (FB = y) && PCI + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC + help + The IMS Twin Turbo is a PCI-based frame buffer card bundled with + many Macintosh and compatible computers. + +config FB_VGA16 + tristate "VGA 16-color graphics support" + depends on FB && (X86 || PPC) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for VGA 16 color graphic + cards. Say Y if you have such a card. + + To compile this driver as a module, choose M here: the + module will be called vga16fb. + +config FB_STI + tristate "HP STI frame buffer device support" + depends on FB && PARISC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + default y + ---help--- + STI refers to the HP "Standard Text Interface" which is a set of + BIOS routines contained in a ROM chip in HP PA-RISC based machines. + Enabling this option will implement the linux framebuffer device + using calls to the STI BIOS routines for initialisation. + + If you enable this option, you will get a planar framebuffer device + /dev/fb which will work on the most common HP graphic cards of the + NGLE family, including the artist chips (in the 7xx and Bxxx series), + HCRX, HCRX24, CRX, CRX24 and VisEG series. + + It is safe to enable this option, so you should probably say "Y". + +config FB_MAC + bool "Generic Macintosh display support" + depends on (FB = y) && MAC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + +# bool ' Apple DAFB display support' CONFIG_FB_DAFB +config FB_HP300 + bool + depends on (FB = y) && HP300 + select FB_CFB_FILLRECT + select FB_CFB_IMAGEBLIT + default y + +config FB_TGA + tristate "TGA framebuffer support" + depends on FB && ALPHA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for generic TGA graphic + cards. Say Y if you have one of those. + +config FB_VESA + bool "VESA VGA graphics support" + depends on (FB = y) && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for generic VESA 2.0 + compliant graphic cards. The older VESA 1.2 cards are not supported. + You will get a boot time penguin logo at no additional cost. Please + read . If unsure, say Y. + +config VIDEO_SELECT + bool + depends on FB_VESA + default y + +config FB_HGA + tristate "Hercules mono graphics support" + depends on FB && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y here if you have a Hercules mono graphics card. + + To compile this driver as a module, choose M here: the + module will be called hgafb. + + As this card technology is 15 years old, most people will answer N + here. + +config FB_HGA_ACCEL + bool "Hercules mono Acceleration functions (EXPERIMENTAL)" + depends on FB_HGA && EXPERIMENTAL + ---help--- + This will compile the Hercules mono graphics with + acceleration functions. + + +config VIDEO_SELECT + bool + depends on (FB = y) && X86 + default y + +config FB_SGIVW + tristate "SGI Visual Workstation framebuffer support" + depends on FB && X86_VISWS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + SGI Visual Workstation support for framebuffer graphics. + +config FB_GBE + bool "SGI Graphics Backend frame buffer support" + depends on (FB = y) && (SGI_IP32 || X86_VISWS) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for SGI Graphics Backend. + This chip is used in SGI O2 and Visual Workstation 320/540. + +config FB_GBE_MEM + int "Video memory size in MB" + depends on FB_GBE + default 8 + help + This is the amount of memory reserved for the framebuffer, + which can be any value between 1MB and 8MB. + +config FB_SUN3 + bool "Sun3 framebuffer support" + depends on (FB = y) && (SUN3 || SUN3X) && BROKEN + +config FB_SBUS + bool "SBUS and UPA framebuffers" + depends on (FB = y) && SPARC + help + Say Y if you want support for SBUS or UPA based frame buffer device. + +config FB_BW2 + bool "BWtwo support" + depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the BWtwo frame buffer. + +config FB_CG3 + bool "CGthree support" + depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the CGthree frame buffer. + +config FB_CG6 + bool "CGsix (GX,TurboGX) support" + depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the CGsix (GX, TurboGX) + frame buffer. + +config FB_PVR2 + tristate "NEC PowerVR 2 display support" + depends on FB && SH_DREAMCAST + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Say Y here if you have a PowerVR 2 card in your box. If you plan to + run linux on your Dreamcast, you will have to say Y here. + This driver may or may not work on other PowerVR 2 cards, but is + totally untested. Use at your own risk. If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pvr2fb. + + You can pass several parameters to the driver at boot time or at + module load time. The parameters look like "video=pvr2:XXX", where + the meaning of XXX can be found at the end of the main source file + (). Please see the file + . + +config FB_EPSON1355 + bool "Epson 1355 framebuffer support" + depends on (FB = y) && (SUPERH || ARCH_CEIVA) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Build in support for the SED1355 Epson Research Embedded RAMDAC + LCD/CRT Controller (since redesignated as the S1D13505) as a + framebuffer. Product specs at + . + +config FB_S1D13XXX + tristate "Epson S1D13XXX framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for S1D13XXX framebuffer device family (currently only + working with S1D13806). Product specs at + + +config FB_NVIDIA + tristate "nVidia Framebuffer Support" + depends on FB && PCI + select I2C_ALGOBIT if FB_NVIDIA_I2C + select I2C if FB_NVIDIA_I2C + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports graphics boards with the nVidia chips, TNT + and newer. For very old chipsets, such as the RIVA128, then use + the rivafb. + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called nvidiafb. + +config FB_NVIDIA_I2C + bool "Enable DDC Support" + depends on FB_NVIDIA + help + This enables I2C support for nVidia Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_RIVA + tristate "nVidia Riva support" + depends on FB && PCI + select I2C_ALGOBIT if FB_RIVA_I2C + select I2C if FB_RIVA_I2C + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports graphics boards with the nVidia Riva/Geforce + chips. + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called rivafb. + +config FB_RIVA_I2C + bool "Enable DDC Support" + depends on FB_RIVA + help + This enables I2C support for nVidia Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_RIVA_DEBUG + bool "Lots of debug output from Riva(nVidia) driver" + depends on FB_RIVA + default n + help + Say Y here if you want the Riva driver to output all sorts + of debugging informations to provide to the maintainer when + something goes wrong. + +config FB_I810 + tristate "Intel 810/815 support (EXPERIMENTAL)" + depends on FB && EXPERIMENTAL && PCI && X86_32 + select AGP + select AGP_INTEL + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports the on-board graphics built in to the Intel 810 + and 815 chipsets. Say Y if you have and plan to use such a board. + + To compile this driver as a module, choose M here: the + module will be called i810fb. + + For more information, please read + + +config FB_I810_GTF + bool "use VESA Generalized Timing Formula" + depends on FB_I810 + help + If you say Y, then the VESA standard, Generalized Timing Formula + or GTF, will be used to calculate the required video timing values + per video mode. Since the GTF allows nondiscrete timings + (nondiscrete being a range of values as opposed to discrete being a + set of values), you'll be able to use any combination of horizontal + and vertical resolutions, and vertical refresh rates without having + to specify your own timing parameters. This is especially useful + to maximize the performance of an aging display, or if you just + have a display with nonstandard dimensions. A VESA compliant + monitor is recommended, but can still work with non-compliant ones. + If you need or want this, then select this option. The timings may + not be compliant with Intel's recommended values. Use at your own + risk. + + If you say N, the driver will revert to discrete video timings + using a set recommended by Intel in their documentation. + + If unsure, say N. + +config FB_I810_I2C + bool "Enable DDC Support" + depends on FB_I810 && FB_I810_GTF + select I2C + select I2C_ALGOBIT + help + +config FB_INTEL + tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" + depends on FB && EXPERIMENTAL && PCI && X86_32 + select AGP + select AGP_INTEL + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports the on-board graphics built in to the Intel + 830M/845G/852GM/855GM/865G chipsets. + Say Y if you have and plan to use such a board. + + To compile this driver as a module, choose M here: the + module will be called intelfb. + +config FB_INTEL_DEBUG + bool "Intel driver Debug Messages" + depends on FB_INTEL + ---help--- + Say Y here if you want the Intel driver to output all sorts + of debugging informations to provide to the maintainer when + something goes wrong. + +config FB_MATROX + tristate "Matrox acceleration" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_MACMODES if PPC_PMAC + ---help--- + Say Y here if you have a Matrox Millennium, Matrox Millennium II, + Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox + Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video, + Matrox G400, G450 or G550 card in your box. + + To compile this driver as a module, choose M here: the + module will be called matroxfb. + + You can pass several parameters to the driver at boot time or at + module load time. The parameters look like "video=matrox:XXX", and + are described in . + +config FB_MATROX_MILLENIUM + bool "Millennium I/II support" + depends on FB_MATROX + help + Say Y here if you have a Matrox Millennium or Matrox Millennium II + video card. If you select "Advanced lowlevel driver options" below, + 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 widths different from 8. + +config FB_MATROX_MYSTIQUE + bool "Mystique support" + depends on FB_MATROX + help + Say Y here if you have a Matrox Mystique or Matrox Mystique 220 + video card. If you select "Advanced lowlevel driver options" below, + 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. + +config FB_MATROX_G + bool "G100/G200/G400/G450/G550 support" + depends on FB_MATROX + ---help--- + Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based + video card. 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. + + If you need support for G400 secondary head, you must first say Y to + "I2C support" in the character devices section, and then to + "Matrox I2C support" and "G400 second head support" here in the + framebuffer section. G450/G550 secondary head and digital output + are supported without additional modules. + + The driver starts in monitor mode. You must use the matroxset tool + (available at ) to + swap primary and secondary head outputs, or to change output mode. + Secondary head driver always start in 640x480 resolution and you + must use fbset to change it. + + Do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). + + G450/G550 hardware can display TV picture only from secondary CRTC, + and it performs no scaling, so picture must have 525 or 625 lines. + +config FB_MATROX_I2C + tristate "Matrox I2C support" + depends on FB_MATROX && I2C + select I2C_ALGOBIT + ---help--- + This drivers creates I2C buses which are needed for accessing the + DDC (I2C) bus present on all Matroxes, an I2C bus which + interconnects Matrox optional devices, like MGA-TVO on G200 and + G400, and the secondary head DDC bus, present on G400 only. + + You can say Y or M here if you want to experiment with monitor + detection code. You must say Y or M here if you want to use either + second head of G400 or MGA-TVO on G200 or G400. + + If you compile it as module, it will create a module named + i2c-matroxfb. + +config FB_MATROX_MAVEN + tristate "G400 second head support" + depends on FB_MATROX_G && FB_MATROX_I2C + ---help--- + WARNING !!! This support does not work with G450 !!! + + Say Y or M here if you want to use a secondary head (meaning two + monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary + head is not compatible with accelerated XFree 3.3.x SVGA servers - + secondary head output is blanked while you are in X. With XFree + 3.9.17 preview you can use both heads if you use SVGA over fbdev or + the fbdev driver on first head and the fbdev driver on second head. + + If you compile it as module, two modules are created, + matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for + both G200 and G400, matroxfb_crtc2 is needed only by G400. You must + also load i2c-matroxfb to get it to run. + + The driver starts in monitor mode and you must use the matroxset + tool (available at + ) to switch it to + PAL or NTSC or to swap primary and secondary head outputs. + Secondary head driver also always start in 640x480 resolution, you + must use fbset to change it. + + Also do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). + +config FB_MATROX_MULTIHEAD + bool "Multihead support" + depends on FB_MATROX + ---help--- + Say Y here if you have more than one (supported) Matrox device in + your computer and you want to use all of them for different monitors + ("multihead"). If you have only one device, you should say N because + the driver compiled with Y is larger and a bit slower, especially on + ia32 (ix86). + + If you said M to "Matrox unified accelerated driver" and N here, you + will still be able to use several Matrox devices simultaneously: + insert several instances of the module matroxfb into the kernel + with insmod, supplying the parameter "dev=N" where N is 0, 1, etc. + for the different Matrox devices. This method is slightly faster but + uses 40 KB of kernel memory per Matrox card. + + There is no need for enabling 'Matrox multihead support' if you have + only one Matrox card in the box. + +config FB_RADEON_OLD + tristate "ATI Radeon display support (Old driver)" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC + help + Choose this option if you want to use an ATI Radeon graphics card as + a framebuffer device. There are both PCI and AGP versions. You + don't need to choose this to run the Radeon in plain VGA mode. + There is a product page at + . + +config FB_RADEON + tristate "ATI Radeon display support" + depends on FB && PCI + select I2C_ALGOBIT if FB_RADEON_I2C + select I2C if FB_RADEON_I2C + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC_OF + help + Choose this option if you want to use an ATI Radeon graphics card as + a framebuffer device. There are both PCI and AGP versions. You + don't need to choose this to run the Radeon in plain VGA mode. + + If you say Y here and want DDC/I2C support you must first say Y to + "I2C support" and "I2C bit-banging support" in the character devices + section. + + If you say M here then "I2C support" and "I2C bit-banging support" + can be build either as modules or built-in. + + There is a product page at + http://apps.ati.com/ATIcompare/ +config FB_RADEON_I2C + bool "DDC/I2C for ATI Radeon support" + depends on FB_RADEON + default y + help + Say Y here if you want DDC/I2C support for your Radeon board. + +config FB_RADEON_DEBUG + bool "Lots of debug output from Radeon driver" + depends on FB_RADEON + default n + help + Say Y here if you want the Radeon driver to output all sorts + of debugging informations to provide to the maintainer when + something goes wrong. + +config FB_ATY128 + tristate "ATI Rage128 display support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC_PMAC + help + This driver supports graphics boards with the ATI Rage128 chips. + Say Y if you have such a graphics board and read + . + + To compile this driver as a module, choose M here: the + module will be called aty128fb. + +config FB_ATY + tristate "ATI Mach64 display support" if PCI || ATARI + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC + help + This driver supports graphics boards with the ATI Mach64 chips. + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called atyfb. + +config FB_ATY_CT + bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" + depends on PCI && FB_ATY + default y if SPARC64 && FB_PCI + help + Say Y here to support use of ATI's 64-bit Rage boards (or other + boards based on the Mach64 CT, VT, GT, and LT chipsets) as a + framebuffer device. The ATI product support page for these boards + is at . + +config FB_ATY_GENERIC_LCD + bool "Mach64 generic LCD support (EXPERIMENTAL)" + depends on FB_ATY_CT + help + Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility, + Rage XC, or Rage XL chipset. + +config FB_ATY_GX + bool "Mach64 GX support" if PCI + depends on FB_ATY + default y if ATARI + help + Say Y here to support use of the ATI Mach64 Graphics Expression + board (or other boards based on the Mach64 GX chipset) as a + framebuffer device. The ATI product support page for these boards + is at + . + +config FB_S3TRIO + bool "S3 Trio display support" + depends on (FB = y) && PPC && BROKEN + help + If you have a S3 Trio say Y. Say N for S3 Virge. + +config FB_SAVAGE + tristate "S3 Savage support" + depends on FB && PCI && EXPERIMENTAL + select I2C_ALGOBIT if FB_SAVAGE_I2C + select I2C if FB_SAVAGE_I2C + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports notebooks and computers with S3 Savage PCI/AGP + chips. + + Say Y if you have such a graphics card. + + To compile this driver as a module, choose M here; the module + will be called savagefb. + +config FB_SAVAGE_I2C + bool "Enable DDC2 Support" + depends on FB_SAVAGE + help + This enables I2C support for S3 Savage Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_SAVAGE_ACCEL + bool "Enable Console Acceleration" + depends on FB_SAVAGE + default n + help + This option will compile in console acceleration support. If + the resulting framebuffer console has bothersome glitches, then + choose N here. + +config FB_SIS + tristate "SiS/XGI display support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the SiS 300, 315, 330 + and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. + Specs available at and . + + To compile this driver as a module, choose M here; the module + will be called sisfb. + +config FB_SIS_300 + bool "SiS 300 series support" + depends on FB_SIS + help + Say Y here to support use of the SiS 300/305, 540, 630 and 730. + +config FB_SIS_315 + bool "SiS 315/330/340 series and XGI support" + depends on FB_SIS + help + Say Y here to support use of the SiS 315, 330 and 340 series + (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well + as XGI V3XT, V5, V8 and Z7. + +config FB_NEOMAGIC + tristate "NeoMagic display support" + depends on FB && PCI + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports notebooks with NeoMagic PCI chips. + Say Y if you have such a graphics card. + + To compile this driver as a module, choose M here: the + module will be called neofb. + +config FB_KYRO + tristate "IMG Kyro support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y here if you have a STG4000 / Kyro / PowerVR 3 based + graphics board. + + To compile this driver as a module, choose M here: the + module will be called kyrofb. + +config FB_3DFX + tristate "3Dfx Banshee/Voodoo3 display support" + depends on FB && PCI + select FB_CFB_IMAGEBLIT + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + help + This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 + chips. Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called tdfxfb. + +config FB_3DFX_ACCEL + bool "3Dfx Banshee/Voodoo3 Acceleration functions (EXPERIMENTAL)" + depends on FB_3DFX && EXPERIMENTAL + ---help--- + This will compile the 3Dfx Banshee/Voodoo3 frame buffer device + with acceleration functions. + + +config FB_VOODOO1 + tristate "3Dfx Voodoo Graphics (sst1) support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or + Voodoo2 (cvg) based graphics card. + + To compile this driver as a module, choose M here: the + module will be called sstfb. + + WARNING: Do not use any application that uses the 3D engine + (namely glide) while using this driver. + Please read the for supported + options and other important info support. + +config FB_CYBLA + tristate "Cyberblade/i1 support" + depends on FB && PCI && X86_32 && !64BIT + select FB_CFB_IMAGEBLIT + select VIDEO_SELECT + ---help--- + This driver is supposed to support the Trident Cyberblade/i1 + graphics core integrated in the VIA VT8601A North Bridge, + also known as VIA Apollo PLE133. + + Status: + - Developed, tested and working on EPIA 5000 and EPIA 800. + - Does work reliable on all systems with CRT/LCD connected to + normal VGA ports. + - Should work on systems that do use the internal LCD port, but + this is absolutely not tested. + + Character imageblit, copyarea and rectangle fill are hw accelerated, + ypan scrolling is used by default. + + Please do read . + + To compile this driver as a module, choose M here: the + module will be called cyblafb. + +config FB_TRIDENT + tristate "Trident support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This driver is supposed to support graphics boards with the + Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops + but also on some motherboards. For more information, read + + + Cyberblade/i1 support will be removed soon, use the cyblafb driver + instead. + + Say Y if you have such a graphics board. + + + To compile this driver as a module, choose M here: the + module will be called tridentfb. + +config FB_TRIDENT_ACCEL + bool "Trident Acceleration functions (EXPERIMENTAL)" + depends on FB_TRIDENT && EXPERIMENTAL + ---help--- + This will compile the Trident frame buffer device with + acceleration functions. + +config FB_PM3 + tristate "Permedia3 support" + depends on FB && PCI && BROKEN + help + This is the frame buffer device driver for the 3DLabs Permedia3 + chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & + similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 + and maybe other boards. + +config FB_AU1100 + bool "Au1100 LCD Driver" + depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y + +source "drivers/video/geode/Kconfig" + +config FB_FFB + bool "Creator/Creator3D/Elite3D support" + depends on FB_SBUS && SPARC64 + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Creator, Creator3D, + and Elite3D graphics boards. + +config FB_TCX + bool "TCX (SS4/SS5 only) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the TCX 24/8bit frame + buffer. + +config FB_CG14 + bool "CGfourteen (SX) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the CGfourteen frame + buffer on Desktop SPARCsystems with the SX graphics option. + +config FB_P9100 + bool "P9100 (Sparcbook 3 only) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the P9100 card + supported on Sparcbook 3 machines. + +config FB_LEO + bool "Leo (ZX) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the SBUS-based Sun ZX + (leo) frame buffer cards. + +config FB_PCI + bool "PCI framebuffers" + depends on (FB = y) && PCI && SPARC + +config FB_IGA + bool "IGA 168x display support" + depends on SPARC32 && FB_PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the INTERGRAPHICS 1680 and + successor frame buffer cards. + +config FB_HIT + tristate "HD64461 Frame Buffer support" + depends on FB && HD64461 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Hitachi HD64461 LCD + frame buffer card. + +config FB_PMAG_AA + bool "PMAG-AA TURBOchannel framebuffer support" + depends on (FB = y) && TC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) + used mainly in the MIPS-based DECstation series. + +config FB_PMAG_BA + bool "PMAG-BA TURBOchannel framebuffer support" + depends on (FB = y) && TC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) + used mainly in the MIPS-based DECstation series. + +config FB_PMAGB_B + bool "PMAGB-B TURBOchannel framebuffer support" + depends on (FB = y) && TC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the PMAGB-B TURBOchannel framebuffer card used mainly + in the MIPS-based DECstation series. The card is currently only + supported in 1280x1024x8 mode. + +config FB_MAXINE + bool "Maxine (Personal DECstation) onboard framebuffer support" + depends on (FB = y) && MACH_DECSTATION + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the onboard framebuffer (1024x768x8) in the Personal + DECstation series (Personal DECstation 5000/20, /25, /33, /50, + Codename "Maxine"). + +config FB_TX3912 + bool "TMPTX3912/PR31700 frame buffer support" + depends on (FB = y) && NINO + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core + see . + + Say Y here to enable kernel support for the on-board framebuffer. + +config FB_G364 + bool "G364 frame buffer support" + depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + The G364 driver is the framebuffer used in MIPS Magnum 4000 and + Olivetti M700-10 systems. + +config FB_68328 + bool "Motorola 68328 native frame buffer support" + depends on FB && (M68328 || M68EZ328 || M68VZ328) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y here if you want to support the built-in frame buffer of + the Motorola 68328 CPU family. + +config FB_PXA + tristate "PXA LCD framebuffer support" + depends on FB && ARCH_PXA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Intel + PXA2x0 processor. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called pxafb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + +config FB_PXA_PARAMETERS + bool "PXA LCD command line parameters" + default n + depends on FB_PXA + ---help--- + Enable the use of kernel command line or module parameters + to configure the physical properties of the LCD panel when + using the PXA LCD driver. + + This option allows you to override the panel parameters + supplied by the platform in order to support multiple + different models of flatpanel. If you will only be using a + single model of flatpanel then you can safely leave this + option disabled. + + describes the available parameters. + +config FB_W100 + tristate "W100 frame buffer support" + depends on FB && PXA_SHARPSL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called w100fb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + +config FB_S3C2410 + tristate "S3C2410 LCD framebuffer support" + depends on FB && ARCH_S3C2410 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Samsung + S3C2410 processor. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called s3c2410fb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. +config FB_S3C2410_DEBUG + bool "S3C2410 lcd debug messages" + depends on FB_S3C2410 + help + Turn on debugging messages. Note that you can set/unset at run time + through sysfs + +config FB_VIRTUAL + tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This is a `virtual' frame buffer device. It operates on a chunk of + unswappable kernel memory instead of on the memory of a graphics + board. This means you cannot see any output sent to this frame + buffer device, while it does consume precious memory. The main use + of this frame buffer device is testing and debugging the frame + buffer subsystem. Do NOT enable it for normal systems! To protect + the innocent, it has to be enabled explicitly at boot time using the + kernel option `video=vfb:'. + + To compile this driver as a module, choose M here: the + module will be called vfb. + + If unsure, say N. +if VT + source "drivers/video/console/Kconfig" +endif + +if FB || SGI_NEWPORT_CONSOLE + source "drivers/video/logo/Kconfig" +endif + +if FB && SYSFS + source "drivers/video/backlight/Kconfig" +endif + +endmenu + diff -urN oldtree/drivers/video/Makefile newtree/drivers/video/Makefile --- oldtree/drivers/video/Makefile 2006-01-03 03:21:10.000000000 +0000 +++ newtree/drivers/video/Makefile 2006-02-18 15:29:54.298727336 +0000 @@ -7,6 +7,7 @@ obj-$(CONFIG_VT) += console/ obj-$(CONFIG_LOGO) += logo/ obj-$(CONFIG_SYSFS) += backlight/ +obj-$(CONFIG_FB_SPLASH) += fbsplash.o cfbsplash.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ diff -urN oldtree/drivers/video/cfbsplash.c newtree/drivers/video/cfbsplash.c --- oldtree/drivers/video/cfbsplash.c 1970-01-01 00:00:00.000000000 +0000 +++ newtree/drivers/video/cfbsplash.c 2006-02-18 15:29:54.299727184 +0000 @@ -0,0 +1,472 @@ +/* + * linux/drivers/video/cfbsplash.c -- Framebuffer splash render functions + * + * Copyright (C) 2004 Michal Januszewski + * + * Code based upon "Bootsplash" (C) 2001-2003 + * Volker Poplawski , + * Stefan Reinauer , + * Steffen Winterfeldt , + * Michael Schroeder , + * Ken Wimer . + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "console/fbcon.h" +#include "fbsplash.h" + +#define parse_pixel(shift,bpp,type) \ + do { \ + if (d & (0x80 >> (shift))) \ + dd2[(shift)] = fgx; \ + else \ + dd2[(shift)] = transparent ? *(type *)splash_src : bgx; \ + splash_src += (bpp); \ + } while (0) \ + +extern int get_color(struct vc_data *vc, struct fb_info *info, + u16 c, int is_fg); + +void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) +{ + int i, j, k; + int minlen = min(min(info->var.red.length, info->var.green.length), + info->var.blue.length); + u32 col; + + for (j = i = 0; i < 16; i++) { + k = color_table[i]; + + col = ((vc->vc_palette[j++] >> (8-minlen)) + << info->var.red.offset); + col |= ((vc->vc_palette[j++] >> (8-minlen)) + << info->var.green.offset); + col |= ((vc->vc_palette[j++] >> (8-minlen)) + << info->var.blue.offset); + ((u32 *)info->pseudo_palette)[k] = col; + } +} + +void fbsplash_renderc(struct fb_info *info, int ypos, int xpos, int height, + int width, u8* src, u32 fgx, u32 bgx, u8 transparent) +{ + unsigned int x, y; + u32 dd; + int bytespp = ((info->var.bits_per_pixel + 7) >> 3); + unsigned int d = ypos * info->fix.line_length + xpos * bytespp; + unsigned int ds = (ypos * info->var.xres + xpos) * bytespp; + u16 dd2[4]; + + u8* splash_src = (u8 *)(info->splash.data + ds); + u8* dst = (u8 *)(info->screen_base + d); + + if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres) + return; + + for (y = 0; y < height; y++) { + switch (info->var.bits_per_pixel) { + + case 32: + for (x = 0; x < width; x++) { + + if ((x & 7) == 0) + d = *src++; + if (d & 0x80) + dd = fgx; + else + dd = transparent ? + *(u32 *)splash_src : bgx; + + d <<= 1; + splash_src += 4; + fb_writel(dd, dst); + dst += 4; + } + break; + case 24: + for (x = 0; x < width; x++) { + + if ((x & 7) == 0) + d = *src++; + if (d & 0x80) + dd = fgx; + else + dd = transparent ? + (*(u32 *)splash_src & 0xffffff) : bgx; + + d <<= 1; + splash_src += 3; +#ifdef __LITTLE_ENDIAN + fb_writew(dd & 0xffff, dst); + dst += 2; + fb_writeb((dd >> 16), dst); +#else + fb_writew(dd >> 8, dst); + dst += 2; + fb_writeb(dd & 0xff, dst); +#endif + dst++; + } + break; + case 16: + for (x = 0; x < width; x += 2) { + if ((x & 7) == 0) + d = *src++; + + parse_pixel(0, 2, u16); + parse_pixel(1, 2, u16); +#ifdef __LITTLE_ENDIAN + dd = dd2[0] | (dd2[1] << 16); +#else + dd = dd2[1] | (dd2[0] << 16); +#endif + d <<= 2; + fb_writel(dd, dst); + dst += 4; + } + break; + + case 8: + for (x = 0; x < width; x += 4) { + if ((x & 7) == 0) + d = *src++; + + parse_pixel(0, 1, u8); + parse_pixel(1, 1, u8); + parse_pixel(2, 1, u8); + parse_pixel(3, 1, u8); + +#ifdef __LITTLE_ENDIAN + dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24); +#else + dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24); +#endif + d <<= 4; + fb_writel(dd, dst); + dst += 4; + } + } + + dst += info->fix.line_length - width * bytespp; + splash_src += (info->var.xres - width) * bytespp; + } +} + +#define cc2cx(a) \ + ((info->fix.visual == FB_VISUAL_TRUECOLOR || \ + info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \ + ((u32*)info->pseudo_palette)[a] : a) + +void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx) +{ + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + struct fbcon_ops *ops = info->fbcon_par; + int fg_color, bg_color, transparent; + u8 *src; + u32 bgx, fgx; + u16 c = scr_readw(s); + + fg_color = get_color(vc, info, c, 1); + bg_color = get_color(vc, info, c, 0); + + /* Don't paint the background image if console is blanked */ + transparent = ops->blank_state ? 0 : + (vc->vc_splash.bg_color == bg_color); + + xx = xx * vc->vc_font.width + vc->vc_splash.tx; + yy = yy * vc->vc_font.height + vc->vc_splash.ty; + + fgx = cc2cx(fg_color); + bgx = cc2cx(bg_color); + + while (count--) { + c = scr_readw(s++); + src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * + ((vc->vc_font.width + 7) >> 3); + + fbsplash_renderc(info, yy, xx, vc->vc_font.height, + vc->vc_font.width, src, fgx, bgx, transparent); + xx += vc->vc_font.width; + } +} + +void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + int i; + unsigned int dsize, s_pitch; + struct fbcon_ops *ops = info->fbcon_par; + struct vc_data* vc; + u8 *src; + + /* we really don't need any cursors while the console is blanked */ + if (info->state != FBINFO_STATE_RUNNING || ops->blank_state) + return; + + vc = vc_cons[ops->currcon].d; + + src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC); + if (!src) + return; + + s_pitch = (cursor->image.width + 7) >> 3; + dsize = s_pitch * cursor->image.height; + if (cursor->enable) { + switch (cursor->rop) { + case ROP_XOR: + for (i = 0; i < dsize; i++) + src[i] = cursor->image.data[i] ^ cursor->mask[i]; + break; + case ROP_COPY: + default: + for (i = 0; i < dsize; i++) + src[i] = cursor->image.data[i] & cursor->mask[i]; + break; + } + } else + memcpy(src, cursor->image.data, dsize); + + fbsplash_renderc(info, + cursor->image.dy + vc->vc_splash.ty, + cursor->image.dx + vc->vc_splash.tx, + cursor->image.height, + cursor->image.width, + (u8*)src, + cc2cx(cursor->image.fg_color), + cc2cx(cursor->image.bg_color), + cursor->image.bg_color == vc->vc_splash.bg_color); + + kfree(src); +} + +static void splashset(u8 *dst, int height, int width, int dstbytes, + u32 bgx, int bpp) +{ + int i; + + if (bpp == 8) + bgx |= bgx << 8; + if (bpp == 16 || bpp == 8) + bgx |= bgx << 16; + + while (height-- > 0) { + u8 *p = dst; + + switch (bpp) { + + case 32: + for (i=0; i < width; i++) { + fb_writel(bgx, p); p += 4; + } + break; + case 24: + for (i=0; i < width; i++) { +#ifdef __LITTLE_ENDIAN + fb_writew((bgx & 0xffff),(u16*)p); p += 2; + fb_writeb((bgx >> 16),p++); +#else + fb_writew((bgx >> 8),(u16*)p); p += 2; + fb_writeb((bgx & 0xff),p++); +#endif + } + case 16: + for (i=0; i < width/4; i++) { + fb_writel(bgx,p); p += 4; + fb_writel(bgx,p); p += 4; + } + if (width & 2) { + fb_writel(bgx,p); p += 4; + } + if (width & 1) + fb_writew(bgx,(u16*)p); + break; + case 8: + for (i=0; i < width/4; i++) { + fb_writel(bgx,p); p += 4; + } + + if (width & 2) { + fb_writew(bgx,p); p += 2; + } + if (width & 1) + fb_writeb(bgx,(u8*)p); + break; + + } + dst += dstbytes; + } +} + +void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes, + int srclinebytes, int bpp) +{ + int i; + + while (height-- > 0) { + u32 *p = (u32 *)dst; + u32 *q = (u32 *)src; + + switch (bpp) { + + case 32: + for (i=0; i < width; i++) + fb_writel(*q++, p++); + break; + case 24: + for (i=0; i < (width*3/4); i++) + fb_writel(*q++, p++); + if ((width*3) % 4) { + if (width & 2) { + fb_writeb(*(u8*)q, (u8*)p); + } else if (width & 1) { + fb_writew(*(u16*)q, (u16*)p); + fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2)); + } + } + break; + case 16: + for (i=0; i < width/4; i++) { + fb_writel(*q++, p++); + fb_writel(*q++, p++); + } + if (width & 2) + fb_writel(*q++, p++); + if (width & 1) + fb_writew(*(u16*)q, (u16*)p); + break; + case 8: + for (i=0; i < width/4; i++) + fb_writel(*q++, p++); + + if (width & 2) { + fb_writew(*(u16*)q, (u16*)p); + q = (u32*) ((u16*)q + 1); + p = (u32*) ((u16*)p + 1); + } + if (width & 1) + fb_writeb(*(u8*)q, (u8*)p); + break; + } + + dst += linebytes; + src += srclinebytes; + } +} + +static void splashfill(struct fb_info *info, int sy, int sx, int height, + int width) +{ + int bytespp = ((info->var.bits_per_pixel + 7) >> 3); + int d = sy * info->fix.line_length + sx * bytespp; + int ds = (sy * info->var.xres + sx) * bytespp; + + fbsplash_copy((u8 *)(info->screen_base + d), (u8 *)(info->splash.data + ds), + height, width, info->fix.line_length, info->var.xres * bytespp, + info->var.bits_per_pixel); +} + +void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, + int height, int width) +{ + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + int bg_color = attr_bgcol_ec(bgshift, vc); + int transparent = vc->vc_splash.bg_color == bg_color; + struct fbcon_ops *ops = info->fbcon_par; + u8 *dst; + + sy = sy * vc->vc_font.height + vc->vc_splash.ty; + sx = sx * vc->vc_font.width + vc->vc_splash.tx; + height *= vc->vc_font.height; + width *= vc->vc_font.width; + + /* Don't paint the background image if console is blanked */ + if (transparent && !ops->blank_state) { + splashfill(info, sy, sx, height, width); + } else { + dst = (u8 *)(info->screen_base + sy * info->fix.line_length + + sx * ((info->var.bits_per_pixel + 7) >> 3)); + splashset(dst, height, width, info->fix.line_length, cc2cx(bg_color), + info->var.bits_per_pixel); + } +} + +void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int tw = vc->vc_cols*vc->vc_font.width; + unsigned int th = vc->vc_rows*vc->vc_font.height; + + if (!bottom_only) { + /* top margin */ + splashfill(info, 0, 0, vc->vc_splash.ty, info->var.xres); + /* left margin */ + splashfill(info, vc->vc_splash.ty, 0, th, vc->vc_splash.tx); + /* right margin */ + splashfill(info, vc->vc_splash.ty, vc->vc_splash.tx + tw, th, + info->var.xres - vc->vc_splash.tx - tw); + } + splashfill(info, vc->vc_splash.ty + th, 0, + info->var.yres - vc->vc_splash.ty - th, info->var.xres); +} + +void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, + int sx, int dx, int width) +{ + u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2); + u16 *s = d + (dx - sx); + u16 *start = d; + u16 *ls = d; + u16 *le = d + width; + u16 c; + int x = dx; + u16 attr = 1; + + do { + c = scr_readw(d); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (d > start) { + fbsplash_putcs(vc, info, start, d - start, y, x); + x += d - start; + start = d; + } + } + if (s >= ls && s < le && c == scr_readw(s)) { + if (d > start) { + fbsplash_putcs(vc, info, start, d - start, y, x); + x += d - start + 1; + start = d + 1; + } else { + x++; + start++; + } + } + s++; + d++; + } while (d < le); + if (d > start) + fbsplash_putcs(vc, info, start, d - start, y, x); +} + +void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank) +{ + if (blank) { + splashset((u8 *)info->screen_base, info->var.yres, info->var.xres, + info->fix.line_length, 0, info->var.bits_per_pixel); + } else { + update_screen(vc); + fbsplash_clear_margins(vc, info, 0); + } +} + diff -urN oldtree/drivers/video/console/bitblit.c newtree/drivers/video/console/bitblit.c --- oldtree/drivers/video/console/bitblit.c 2006-02-18 15:18:29.176881688 +0000 +++ newtree/drivers/video/console/bitblit.c 2006-02-18 15:29:54.300727032 +0000 @@ -18,6 +18,7 @@ #include #include #include "fbcon.h" +#include "../fbsplash.h" /* * Accelerated handlers. @@ -55,6 +56,13 @@ area.height = height * vc->vc_font.height; area.width = width * vc->vc_font.width; + if (fbsplash_active(info, vc)) { + area.sx += vc->vc_splash.tx; + area.sy += vc->vc_splash.ty; + area.dx += vc->vc_splash.tx; + area.dy += vc->vc_splash.ty; + } + info->fbops->fb_copyarea(info, &area); } @@ -380,11 +388,15 @@ cursor.image.depth = 1; cursor.rop = ROP_XOR; - if (info->fbops->fb_cursor) - err = info->fbops->fb_cursor(info, &cursor); + if (fbsplash_active(info, vc)) { + fbsplash_cursor(info, &cursor); + } else { + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); - if (err) - soft_cursor(info, &cursor); + if (err) + soft_cursor(info, &cursor); + } ops->cursor_reset = 0; } diff -urN oldtree/drivers/video/console/fbcon.c newtree/drivers/video/console/fbcon.c --- oldtree/drivers/video/console/fbcon.c 2006-02-18 15:18:29.177881536 +0000 +++ newtree/drivers/video/console/fbcon.c 2006-02-18 15:29:54.302726728 +0000 @@ -93,6 +93,7 @@ #endif #include "fbcon.h" +#include "../fbsplash.h" #ifdef FBCONDEBUG # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) @@ -108,7 +109,7 @@ static struct display fb_display[MAX_NR_CONSOLES]; -static signed char con2fb_map[MAX_NR_CONSOLES]; +signed char con2fb_map[MAX_NR_CONSOLES]; static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static int logo_height; static int logo_lines; @@ -298,7 +299,7 @@ vc->vc_mode != KD_TEXT || ops->graphics); } -static inline int get_color(struct vc_data *vc, struct fb_info *info, +inline int get_color(struct vc_data *vc, struct fb_info *info, u16 c, int is_fg) { int depth = fb_get_color_depth(&info->var, &info->fix); @@ -404,6 +405,7 @@ CM_ERASE : CM_DRAW; ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1), get_color(vc, info, c, 0)); + release_console_sem(); } @@ -568,6 +570,8 @@ info_idx = -1; } + fbsplash_init(); + return err; } @@ -971,6 +975,12 @@ rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; + + if (fbsplash_active(info, vc)) { + cols = vc->vc_splash.twidth / vc->vc_font.width; + rows = vc->vc_splash.theight / vc->vc_font.height; + } + vc_resize(vc, cols, rows); DPRINTK("mode: %s\n", info->fix.id); @@ -1053,7 +1063,7 @@ cap = info->flags; if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW || - (info->fix.type == FB_TYPE_TEXT)) + (info->fix.type == FB_TYPE_TEXT) || fbsplash_active(info, vc)) logo = 0; if (var_to_display(p, &info->var, info)) @@ -1193,6 +1203,11 @@ if (!height || !width) return; + if (fbsplash_active(info, vc)) { + fbsplash_clear(vc, info, sy, sx, height, width); + return; + } + /* Split blits that cross physical y_wrap boundary */ y_break = p->vrows - p->yscroll; @@ -1212,10 +1227,15 @@ struct display *p = &fb_display[vc->vc_num]; struct fbcon_ops *ops = info->fbcon_par; - if (!fbcon_is_inactive(vc, info)) - ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, - get_color(vc, info, scr_readw(s), 1), - get_color(vc, info, scr_readw(s), 0)); + if (!fbcon_is_inactive(vc, info)) { + + if (fbsplash_active(info, vc)) + fbsplash_putcs(vc, info, s, count, ypos, xpos); + else + ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, + get_color(vc, info, scr_readw(s), 1), + get_color(vc, info, scr_readw(s), 0)); + } } static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) @@ -1231,8 +1251,13 @@ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; - if (!fbcon_is_inactive(vc, info)) - ops->clear_margins(vc, info, bottom_only); + if (!fbcon_is_inactive(vc, info)) { + if (fbsplash_active(info, vc)) { + fbsplash_clear_margins(vc, info, bottom_only); + } else { + ops->clear_margins(vc, info, bottom_only); + } + } } static void fbcon_cursor(struct vc_data *vc, int mode) @@ -1705,7 +1730,7 @@ count = vc->vc_rows; if (softback_top) fbcon_softback_note(vc, t, count); - if (logo_shown >= 0) + if (logo_shown >= 0 || fbsplash_active(info, vc)) goto redraw_up; switch (p->scrollmode) { case SCROLL_MOVE: @@ -1793,6 +1818,8 @@ count = vc->vc_rows; if (logo_shown >= 0) goto redraw_down; + if (fbsplash_active(info, vc)) + goto redraw_down; switch (p->scrollmode) { case SCROLL_MOVE: ops->bmove(vc, info, t, 0, t + count, 0, @@ -1935,6 +1962,13 @@ } return; } + + if (fbsplash_active(info, vc) && sy == dy && height == 1) { + /* must use slower redraw bmove to keep background pic intact */ + fbsplash_bmove_redraw(vc, info, sy, sx, dx, width); + return; + } + ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, height, width); } @@ -2005,8 +2039,9 @@ var.yres = virt_h * virt_fh; x_diff = info->var.xres - var.xres; y_diff = info->var.yres - var.yres; - if (x_diff < 0 || x_diff > virt_fw || - y_diff < 0 || y_diff > virt_fh) { + + if ((x_diff < 0 || x_diff > virt_fw || + y_diff < 0 || y_diff > virt_fh) && !vc->vc_splash.state) { struct fb_videomode *mode; DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); @@ -2042,7 +2077,26 @@ info = registered_fb[con2fb_map[vc->vc_num]]; ops = info->fbcon_par; - + prev_console = ops->currcon; + if (prev_console != -1) + old_info = registered_fb[con2fb_map[prev_console]]; + + if (fbsplash_active_vc(vc)) { + struct vc_data *vc_curr = vc_cons[prev_console].d; + if (!vc_curr->vc_splash.theme || strcmp(vc->vc_splash.theme, vc_curr->vc_splash.theme)) { + if (fbsplash_call_helper("getpic", vc->vc_num)) + fbsplash_disable(vc, 0); + } + } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + struct vc_data *vc_curr = vc_cons[prev_console].d; + if (vc_curr && fbsplash_active_vc(vc_curr)) { + /* Clear the screen to avoid displaying funky colors during + * palette updates. */ + memset((u8*)info->screen_base + info->fix.line_length * info->var.yoffset, + 0, info->var.yres * info->fix.line_length); + } + } + if (softback_top) { if (softback_lines) fbcon_set_origin(vc); @@ -2060,9 +2114,6 @@ logo_shown = FBCON_LOGO_CANSHOW; } - prev_console = ops->currcon; - if (prev_console != -1) - old_info = registered_fb[con2fb_map[prev_console]]; /* * FIXME: If we have multiple fbdev's loaded, we need to * update all info->currcon. Perhaps, we can place this @@ -2104,6 +2155,11 @@ } } + if (fbsplash_active_nores(info, vc) && !fbsplash_active(info, vc)) { + if (fbsplash_call_helper("modechange", vc->vc_num)) + fbsplash_disable(vc, 0); + } + set_blitting_type(vc, info); ops->cursor_reset = 1; @@ -2205,8 +2261,12 @@ fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); ops->cursor_flash = (!blank); - if (fb_blank(info, blank)) - fbcon_generic_blank(vc, info, blank); + if (fb_blank(info, blank)) { + if (fbsplash_active(info, vc)) + fbsplash_blank(vc, info, blank); + else + fbcon_generic_blank(vc, info, blank); + } } if (!blank) @@ -2364,13 +2424,22 @@ } if (resize) { + /* reset wrap/pan */ int cols, rows; cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + + info->var.xoffset = info->var.yoffset = p->yscroll = 0; + if (fbsplash_active(info, vc)) { + cols = vc->vc_splash.twidth; + rows = vc->vc_splash.theight; + } cols /= w; rows /= h; + vc_resize(vc, cols, rows); + if (CON_IS_VISIBLE(vc) && softback_buf) fbcon_update_softback(vc); } else if (CON_IS_VISIBLE(vc) @@ -2488,7 +2557,7 @@ int i, j, k, depth; u8 val; - if (fbcon_is_inactive(vc, info)) + if (fbcon_is_inactive(vc, info) || vc->vc_num != fg_console) return -EINVAL; if (!CON_IS_VISIBLE(vc)) @@ -2514,7 +2583,49 @@ } else fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap); - return fb_set_cmap(&palette_cmap, info); + if (fbsplash_active(info, vc_cons[fg_console].d) && + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + + u16 *red, *green, *blue; + int minlen = min(min(info->var.red.length, info->var.green.length), + info->var.blue.length); + int h; + + struct fb_cmap cmap = { + .start = 0, + .len = (1 << minlen), + .red = NULL, + .green = NULL, + .blue = NULL, + .transp = NULL + }; + + red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL); + + if (!red) + goto out; + + green = red + 256; + blue = green + 256; + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + + for (i = 0; i < cmap.len; i++) { + red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1); + } + + h = fb_set_cmap(&cmap, info); + fbsplash_fix_pseudo_pal(info, vc_cons[fg_console].d); + kfree(red); + + return h; + + } else if (fbsplash_active(info, vc_cons[fg_console].d) && + info->var.bits_per_pixel == 8 && info->splash.cmap.red != NULL) + fb_set_cmap(&info->splash.cmap, info); + +out: return fb_set_cmap(&palette_cmap, info); } static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) @@ -2740,7 +2851,14 @@ rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; - vc_resize(vc, cols, rows); + + if (!fbsplash_active_nores(info, vc)) { + vc_resize(vc, cols, rows); + } else { + if (fbsplash_call_helper("modechange", vc->vc_num)) + fbsplash_disable(vc, 0); + } + updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; diff -urN oldtree/drivers/video/fbcmap.c newtree/drivers/video/fbcmap.c --- oldtree/drivers/video/fbcmap.c 2006-01-03 03:21:10.000000000 +0000 +++ newtree/drivers/video/fbcmap.c 2006-02-18 15:29:54.303726576 +0000 @@ -16,6 +16,7 @@ #include #include #include +#include "fbsplash.h" #include @@ -235,14 +236,17 @@ if (transp) htransp = *transp++; if (info->fbops->fb_setcolreg(start++, - hred, hgreen, hblue, + hred, hgreen, hblue, htransp, info)) break; } } - if (rc == 0) + if (rc == 0) { fb_copy_cmap(cmap, &info->cmap); - + if (fbsplash_active(info, vc_cons[fg_console].d) && + info->fix.visual == FB_VISUAL_DIRECTCOLOR) + fbsplash_fix_pseudo_pal(info, vc_cons[fg_console].d); + } return rc; } @@ -250,7 +254,7 @@ { int rc, size = cmap->len * sizeof(u16); struct fb_cmap umap; - + if (cmap->start < 0 || (!info->fbops->fb_setcolreg && !info->fbops->fb_setcmap)) return -EINVAL; diff -urN oldtree/drivers/video/fbsplash.c newtree/drivers/video/fbsplash.c --- oldtree/drivers/video/fbsplash.c 1970-01-01 00:00:00.000000000 +0000 +++ newtree/drivers/video/fbsplash.c 2006-02-18 15:29:54.305726272 +0000 @@ -0,0 +1,406 @@ +/* + * linux/drivers/video/fbsplash.c -- Framebuffer splash routines + * + * Copyright (C) 2004 Michal Januszewski + * + * Code based upon "Bootsplash" (C) 2001-2003 + * Volker Poplawski , + * Stefan Reinauer , + * Steffen Winterfeldt , + * Michael Schroeder , + * Ken Wimer . + * + * Splash render routines are located in /linux/drivers/video/cfbsplash.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "console/fbcon.h" +#include "fbsplash.h" + +#define SPLASH_VERSION "0.9.2" + +extern signed char con2fb_map[]; +static int fbsplash_enable(struct vc_data *vc); +char fbsplash_path[KMOD_PATH_LEN] = "/sbin/splash_helper"; + +int fbsplash_call_helper(char* cmd, unsigned short vc) +{ + char *envp[] = { + "HOME=/", + "PATH=/sbin:/bin", + NULL + }; + + char tfb[5]; + char tcons[5]; + unsigned char fb = (int) con2fb_map[vc]; + + char *argv[] = { + fbsplash_path, + "2", + cmd, + tcons, + tfb, + vc_cons[vc].d->vc_splash.theme, + NULL + }; + + snprintf(tfb,5,"%d",fb); + snprintf(tcons,5,"%d",vc); + + return call_usermodehelper(fbsplash_path, argv, envp, 1); +} + +/* Disables fbsplash on a virtual console; called with console sem held. */ +int fbsplash_disable(struct vc_data *vc, unsigned char redraw) +{ + struct fb_info* info; + + if (!vc->vc_splash.state) + return -EINVAL; + + info = registered_fb[(int) con2fb_map[vc->vc_num]]; + + if (info == NULL) + return -EINVAL; + + vc->vc_splash.state = 0; + vc_resize(vc, info->var.xres / vc->vc_font.width, + info->var.yres / vc->vc_font.height); + + if (fg_console == vc->vc_num && redraw) { + redraw_screen(vc, 0); + update_region(vc, vc->vc_origin + + vc->vc_size_row * vc->vc_top, + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); + } + + printk(KERN_INFO "fbsplash: switched splash state to 'off' on console %d\n", + vc->vc_num); + + return 0; +} + +/* Enables fbsplash on a virtual console; called with console sem held. */ +static int fbsplash_enable(struct vc_data *vc) +{ + struct fb_info* info; + + info = registered_fb[(int) con2fb_map[vc->vc_num]]; + + if (vc->vc_splash.twidth == 0 || vc->vc_splash.theight == 0 || + info == NULL || vc->vc_splash.state || (!info->splash.data && + vc->vc_num == fg_console)) + return -EINVAL; + + vc->vc_splash.state = 1; + vc_resize(vc, vc->vc_splash.twidth / vc->vc_font.width, + vc->vc_splash.theight / vc->vc_font.height); + + if (fg_console == vc->vc_num) { + redraw_screen(vc, 0); + update_region(vc, vc->vc_origin + + vc->vc_size_row * vc->vc_top, + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); + fbsplash_clear_margins(vc, info, 0); + } + + printk(KERN_INFO "fbsplash: switched splash state to 'on' on console %d\n", + vc->vc_num); + + return 0; +} + +static inline int fbsplash_ioctl_dosetstate(struct vc_data *vc, unsigned int __user* state, unsigned char origin) +{ + int tmp, ret; + + if (get_user(tmp, state)) + return -EFAULT; + + if (origin == FB_SPLASH_IO_ORIG_USER) + acquire_console_sem(); + if (!tmp) + ret = fbsplash_disable(vc, 1); + else + ret = fbsplash_enable(vc); + if (origin == FB_SPLASH_IO_ORIG_USER) + release_console_sem(); + + return ret; +} + +static inline int fbsplash_ioctl_dogetstate(struct vc_data *vc, unsigned int __user *state) +{ + return put_user(vc->vc_splash.state, (unsigned int __user*) state); +} + +static int fbsplash_ioctl_dosetcfg(struct vc_data *vc, struct vc_splash __user *arg, unsigned char origin) +{ + struct vc_splash cfg; + struct fb_info *info; + int len; + char *tmp; + + info = registered_fb[(int) con2fb_map[vc->vc_num]]; + + if (copy_from_user(&cfg, arg, sizeof(struct vc_splash))) + return -EFAULT; + if (info == NULL || !cfg.twidth || !cfg.theight || + cfg.tx + cfg.twidth > info->var.xres || + cfg.ty + cfg.theight > info->var.yres) + return -EINVAL; + + len = strlen_user(cfg.theme); + if (!len || len > FB_SPLASH_THEME_LEN) + return -EINVAL; + tmp = kmalloc(len, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + if (copy_from_user(tmp, (void __user *)cfg.theme, len)) + return -EFAULT; + cfg.theme = tmp; + cfg.state = 0; + + /* If this ioctl is a response to a request from kernel, the console sem + * is already held; we also don't need to disable splash because either the + * new config and background picture will be successfully loaded, and the + * splash will stay on, or in case of a failure it'll be turned off in fbcon. */ + if (origin == FB_SPLASH_IO_ORIG_USER) { + acquire_console_sem(); + if (vc->vc_splash.state) + fbsplash_disable(vc, 1); + } + + if (vc->vc_splash.theme) + kfree(vc->vc_splash.theme); + + vc->vc_splash = cfg; + + if (origin == FB_SPLASH_IO_ORIG_USER) + release_console_sem(); + + printk(KERN_INFO "fbsplash: console %d using theme '%s'\n", + vc->vc_num, vc->vc_splash.theme); + return 0; +} + +static int fbsplash_ioctl_dogetcfg(struct vc_data *vc, struct vc_splash __user *arg) +{ + struct vc_splash splash; + char __user *tmp; + + if (get_user(tmp, &arg->theme)) + return -EFAULT; + + splash = vc->vc_splash; + splash.theme = tmp; + + if (vc->vc_splash.theme) { + if (copy_to_user(tmp, vc->vc_splash.theme, strlen(vc->vc_splash.theme) + 1)) + return -EFAULT; + } else + if (put_user(0, tmp)) + return -EFAULT; + + if (copy_to_user(arg, &splash, sizeof(struct vc_splash))) + return -EFAULT; + + return 0; +} + +static int fbsplash_ioctl_dosetpic(struct vc_data *vc, struct fb_image __user *arg, unsigned char origin) +{ + struct fb_image img; + struct fb_info *info; + int len; + u8 *tmp; + + if (vc->vc_num != fg_console) + return -EINVAL; + + info = registered_fb[(int) con2fb_map[vc->vc_num]]; + + if (info == NULL) + return -EINVAL; + + if (copy_from_user(&img, arg, sizeof(struct fb_image))) + return -EFAULT; + + if (img.width != info->var.xres || img.height != info->var.yres) { + printk(KERN_ERR "fbsplash: picture dimensions mismatch\n"); + return -EINVAL; + } + + if (img.depth != info->var.bits_per_pixel) { + printk(KERN_ERR "fbsplash: picture depth mismatch\n"); + return -EINVAL; + } + + if (img.depth == 8) { + if (!img.cmap.len || !img.cmap.red || !img.cmap.green || + !img.cmap.blue) + return -EINVAL; + + tmp = vmalloc(img.cmap.len * 3 * 2); + if (!tmp) + return -ENOMEM; + + if (copy_from_user(tmp, (void __user*)img.cmap.red, img.cmap.len * 2) || + copy_from_user(tmp + (img.cmap.len << 1), + (void __user*)img.cmap.green, (img.cmap.len << 1)) || + copy_from_user(tmp + (img.cmap.len << 2), + (void __user*)img.cmap.blue, (img.cmap.len << 1))) { + vfree(tmp); + return -EFAULT; + } + + img.cmap.transp = NULL; + img.cmap.red = (u16*)tmp; + img.cmap.green = img.cmap.red + img.cmap.len; + img.cmap.blue = img.cmap.green + img.cmap.len; + } else { + img.cmap.red = NULL; + } + + len = ((img.depth + 7) >> 3) * img.width * img.height; + tmp = vmalloc(len); + + if (!tmp) + goto out; + + if (copy_from_user(tmp, (void __user*)img.data, len)) + goto out; + + img.data = tmp; + + /* If this ioctl is a response to a request from kernel, the console sem + * is already held. */ + if (origin == FB_SPLASH_IO_ORIG_USER) + acquire_console_sem(); + + if (info->splash.data) + vfree((u8*)info->splash.data); + if (info->splash.cmap.red) + vfree(info->splash.cmap.red); + + info->splash = img; + + if (origin == FB_SPLASH_IO_ORIG_USER) + release_console_sem(); + + return 0; + +out: if (img.cmap.red) + vfree(img.cmap.red); + if (tmp) + vfree(tmp); + return -ENOMEM; +} + +static int splash_ioctl(struct inode * inode, struct file *filp, u_int cmd, + u_long arg) +{ + struct fb_splash_iowrapper __user *wrapper = (void __user*) arg; + struct vc_data *vc = NULL; + unsigned short vc_num = 0; + unsigned char origin = 0; + void __user *data = NULL; + + if (!access_ok(VERIFY_READ, wrapper, + sizeof(struct fb_splash_iowrapper))) + return -EFAULT; + + __get_user(vc_num, &wrapper->vc); + __get_user(origin, &wrapper->origin); + __get_user(data, &wrapper->data); + + if (!vc_cons_allocated(vc_num)) + return -EINVAL; + + vc = vc_cons[vc_num].d; + + switch (cmd) { + case FBIOSPLASH_SETPIC: + return fbsplash_ioctl_dosetpic(vc, (struct fb_image __user*)data, origin); + case FBIOSPLASH_SETCFG: + return fbsplash_ioctl_dosetcfg(vc, (struct vc_splash*)data, origin); + case FBIOSPLASH_GETCFG: + return fbsplash_ioctl_dogetcfg(vc, (struct vc_splash*)data); + case FBIOSPLASH_SETSTATE: + return fbsplash_ioctl_dosetstate(vc, (unsigned int *)data, origin); + case FBIOSPLASH_GETSTATE: + return fbsplash_ioctl_dogetstate(vc, (unsigned int *)data); + default: + return -ENOIOCTLCMD; + } +} + +static struct file_operations splash_ops = { + .owner = THIS_MODULE, + .ioctl = splash_ioctl +}; + +static struct miscdevice splash_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "fbsplash", + .fops = &splash_ops +}; + +int fbsplash_init(void) +{ + struct fb_info *info; + struct vc_data *vc; + int i; + + vc = vc_cons[0].d; + info = registered_fb[0]; + + for (i = 0; i < num_registered_fb; i++) { + registered_fb[i]->splash.data = NULL; + registered_fb[i]->splash.cmap.red = NULL; + } + + for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) { + vc_cons[i].d->vc_splash.state = vc_cons[i].d->vc_splash.twidth = + vc_cons[i].d->vc_splash.theight = 0; + vc_cons[i].d->vc_splash.theme = NULL; + } + + i = misc_register(&splash_dev); + if (i) { + printk(KERN_ERR "fbsplash: failed to register device\n"); + return i; + } + + fbsplash_call_helper("init", 0); + + return 0; +} + +EXPORT_SYMBOL(fbsplash_path); diff -urN oldtree/drivers/video/fbsplash.h newtree/drivers/video/fbsplash.h --- oldtree/drivers/video/fbsplash.h 1970-01-01 00:00:00.000000000 +0000 +++ newtree/drivers/video/fbsplash.h 2006-02-18 15:29:54.306726120 +0000 @@ -0,0 +1,76 @@ +/* + * linux/drivers/video/fbsplash.h -- Framebuffer splash headers + * + * Copyright (C) 2004 Michal Januszewski + * + */ + +#ifndef __FB_SPLASH_H +#define __FB_SPLASH_H + +#ifndef _LINUX_FB_H +#include +#endif + +/* This is needed for vc_cons in fbcmap.c */ +#include + +struct fb_cursor; +struct fb_info; +struct vc_data; + +#ifdef CONFIG_FB_SPLASH +/* fbsplash.c */ +int fbsplash_init(void); +int fbsplash_call_helper(char* cmd, unsigned short cons); +int fbsplash_disable(struct vc_data *vc, unsigned char redraw); + +/* cfbsplash.c */ +void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx); +void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor); +void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width); +void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only); +void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank); +void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width); +void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp); +void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc); + +/* vt.c */ +void acquire_console_sem(void); +void release_console_sem(void); +void do_unblank_screen(int entering_gfx); + +/* struct vc_data *y */ +#define fbsplash_active_vc(y) (y->vc_splash.state && y->vc_splash.theme) + +/* struct fb_info *x, struct vc_data *y */ +#define fbsplash_active_nores(x,y) (x->splash.data && fbsplash_active_vc(y)) + +/* struct fb_info *x, struct vc_data *y */ +#define fbsplash_active(x,y) (fbsplash_active_nores(x,y) && \ + x->splash.width == x->var.xres && \ + x->splash.height == x->var.yres && \ + x->splash.depth == x->var.bits_per_pixel) + + +#else /* CONFIG_FB_SPLASH */ + +static inline void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {} +static inline void fbsplash_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {} +static inline void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor) {} +static inline void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {} +static inline void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {} +static inline void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank) {} +static inline void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {} +static inline void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {} +static inline int fbsplash_call_helper(char* cmd, unsigned short cons) { return 0; } +static inline int fbsplash_init(void) { return 0; } +static inline int fbsplash_disable(struct vc_data *vc, unsigned char redraw) { return 0; } + +#define fbsplash_active_vc(y) (0) +#define fbsplash_active_nores(x,y) (0) +#define fbsplash_active(x,y) (0) + +#endif /* CONFIG_FB_SPLASH */ + +#endif /* __FB_SPLASH_H */ diff -urN oldtree/include/linux/console_splash.h newtree/include/linux/console_splash.h --- oldtree/include/linux/console_splash.h 1970-01-01 00:00:00.000000000 +0000 +++ newtree/include/linux/console_splash.h 2006-02-18 15:29:54.307725968 +0000 @@ -0,0 +1,13 @@ +#ifndef _LINUX_CONSOLE_SPLASH_H_ +#define _LINUX_CONSOLE_SPLASH_H_ 1 + +/* A structure used by the framebuffer splash code (drivers/video/fbsplash.c) */ +struct vc_splash { + __u8 bg_color; /* The color that is to be treated as transparent */ + __u8 state; /* Current splash state: 0 = off, 1 = on */ + __u16 tx, ty; /* Top left corner coordinates of the text field */ + __u16 twidth, theight; /* Width and height of the text field */ + char* theme; +}; + +#endif diff -urN oldtree/include/linux/console_struct.h newtree/include/linux/console_struct.h --- oldtree/include/linux/console_struct.h 2006-01-03 03:21:10.000000000 +0000 +++ newtree/include/linux/console_struct.h 2006-02-18 15:29:54.308725816 +0000 @@ -14,6 +14,7 @@ struct vt_struct; #define NPAR 16 +#include struct vc_data { unsigned short vc_num; /* Console number */ @@ -97,6 +98,8 @@ struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ unsigned long vc_uni_pagedir; unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ + + struct vc_splash vc_splash; /* additional information is in vt_kern.h */ }; diff -urN oldtree/include/linux/fb.h newtree/include/linux/fb.h --- oldtree/include/linux/fb.h 2006-02-18 15:18:29.892772856 +0000 +++ newtree/include/linux/fb.h 2006-02-18 15:29:54.309725664 +0000 @@ -8,6 +8,13 @@ #define FB_MAJOR 29 #define FB_MAX 32 /* sufficient for now */ +struct fb_splash_iowrapper +{ + unsigned short vc; /* Virtual console */ + unsigned char origin; /* Point of origin of the request */ + void *data; +}; + /* ioctls 0x46 is 'F' */ #define FBIOGET_VSCREENINFO 0x4600 @@ -35,7 +42,15 @@ #define FBIOGET_HWCINFO 0x4616 #define FBIOPUT_MODEINFO 0x4617 #define FBIOGET_DISPINFO 0x4618 - +#define FBIOSPLASH_SETCFG _IOWR('F', 0x19, struct fb_splash_iowrapper) +#define FBIOSPLASH_GETCFG _IOR('F', 0x1A, struct fb_splash_iowrapper) +#define FBIOSPLASH_SETSTATE _IOWR('F', 0x1B, struct fb_splash_iowrapper) +#define FBIOSPLASH_GETSTATE _IOR('F', 0x1C, struct fb_splash_iowrapper) +#define FBIOSPLASH_SETPIC _IOWR('F', 0x1D, struct fb_splash_iowrapper) + +#define FB_SPLASH_THEME_LEN 128 /* Maximum lenght of a theme name */ +#define FB_SPLASH_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */ +#define FB_SPLASH_IO_ORIG_USER 1 /* User ioctl origin */ #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ @@ -769,6 +784,9 @@ #define FBINFO_STATE_SUSPENDED 1 u32 state; /* Hardware state i.e suspend */ void *fbcon_par; /* fbcon use-only private area */ + + struct fb_image splash; + /* From here on everything is device dependent */ void *par; }; diff -urN oldtree/include/linux/sysctl.h newtree/include/linux/sysctl.h --- oldtree/include/linux/sysctl.h 2006-02-18 15:18:29.973760544 +0000 +++ newtree/include/linux/sysctl.h 2006-02-18 15:29:54.310725512 +0000 @@ -146,6 +146,7 @@ KERN_RANDOMIZE=68, /* int: randomize virtual address space */ KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */ KERN_SPIN_RETRY=70, /* int: number of spinlock retries */ + KERN_FBSPLASH=71, /* string: path to fbsplash helper */ }; diff -urN oldtree/kernel/sysctl.c newtree/kernel/sysctl.c --- oldtree/kernel/sysctl.c 2006-02-18 15:18:30.101741088 +0000 +++ newtree/kernel/sysctl.c 2006-02-18 15:29:54.313725056 +0000 @@ -88,6 +88,9 @@ #ifdef CONFIG_KMOD extern char modprobe_path[]; #endif +#ifdef CONFIG_FB_SPLASH +extern char fbsplash_path[]; +#endif #ifdef CONFIG_CHR_DEV_SG extern int sg_big_buff; #endif @@ -404,6 +407,17 @@ .strategy = &sysctl_string, }, #endif +#ifdef CONFIG_FB_SPLASH + { + .ctl_name = KERN_FBSPLASH, + .procname = "fbsplash", + .data = &fbsplash_path, + .maxlen = KMOD_PATH_LEN, + .mode = 0644, + .proc_handler = &proc_dostring, + .strategy = &sysctl_string, + }, +#endif #ifdef CONFIG_CHR_DEV_SG { .ctl_name = KERN_SG_BIG_BUFF, diff -urN oldtree/kernel/sysctl.c.orig newtree/kernel/sysctl.c.orig --- oldtree/kernel/sysctl.c.orig 1970-01-01 00:00:00.000000000 +0000 +++ newtree/kernel/sysctl.c.orig 2006-02-18 15:18:30.000000000 +0000 @@ -0,0 +1,2489 @@ +/* + * sysctl.c: General linux system control interface + * + * Begun 24 March 1995, Stephen Tweedie + * Added /proc support, Dec 1995 + * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas. + * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver. + * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver. + * Dynamic registration fixes, Stephen Tweedie. + * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn. + * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris + * Horn. + * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer. + * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer. + * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill + * Wendling. + * The list_for_each() macro wasn't appropriate for the sysctl loop. + * Removed it and replaced it with older style, 03/23/00, Bill Wendling + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_ROOT_NFS +#include +#endif + +#if defined(CONFIG_SYSCTL) + +/* External variables not in a header file. */ +extern int C_A_D; +extern int sysctl_overcommit_memory; +extern int sysctl_overcommit_ratio; +extern int max_threads; +extern int sysrq_enabled; +extern int core_uses_pid; +extern int suid_dumpable; +extern char core_pattern[]; +extern int cad_pid; +extern int pid_max; +extern int min_free_kbytes; +extern int printk_ratelimit_jiffies; +extern int printk_ratelimit_burst; +extern int pid_max_min, pid_max_max; +extern int sysctl_drop_caches; +extern int percpu_pagelist_fraction; + +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) +int unknown_nmi_panic; +extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t *); +#endif + +/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ +static int maxolduid = 65535; +static int minolduid; +static int min_percpu_pagelist_fract = 8; + +static int ngroups_max = NGROUPS_MAX; + +#ifdef CONFIG_KMOD +extern char modprobe_path[]; +#endif +#ifdef CONFIG_CHR_DEV_SG +extern int sg_big_buff; +#endif +#ifdef CONFIG_SYSVIPC +extern size_t shm_ctlmax; +extern size_t shm_ctlall; +extern int shm_ctlmni; +extern int msg_ctlmax; +extern int msg_ctlmnb; +extern int msg_ctlmni; +extern int sem_ctls[]; +#endif + +#ifdef __sparc__ +extern char reboot_command []; +extern int stop_a_enabled; +extern int scons_pwroff; +#endif + +#ifdef __hppa__ +extern int pwrsw_enabled; +extern int unaligned_enabled; +#endif + +#ifdef CONFIG_S390 +#ifdef CONFIG_MATHEMU +extern int sysctl_ieee_emulation_warnings; +#endif +extern int sysctl_userprocess_debug; +extern int spin_retry; +#endif + +extern int sysctl_hz_timer; + +#ifdef CONFIG_BSD_PROCESS_ACCT +extern int acct_parm[]; +#endif + +static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t, + ctl_table *, void **); +static int proc_doutsstring(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos); + +static ctl_table root_table[]; +static struct ctl_table_header root_table_header = + { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; + +static ctl_table kern_table[]; +static ctl_table vm_table[]; +static ctl_table proc_table[]; +static ctl_table fs_table[]; +static ctl_table debug_table[]; +static ctl_table dev_table[]; +extern ctl_table random_table[]; +#ifdef CONFIG_UNIX98_PTYS +extern ctl_table pty_table[]; +#endif +#ifdef CONFIG_INOTIFY +extern ctl_table inotify_table[]; +#endif + +#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT +int sysctl_legacy_va_layout; +#endif + +/* /proc declarations: */ + +#ifdef CONFIG_PROC_FS + +static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *); +static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *); +static int proc_opensys(struct inode *, struct file *); + +struct file_operations proc_sys_file_operations = { + .open = proc_opensys, + .read = proc_readsys, + .write = proc_writesys, +}; + +extern struct proc_dir_entry *proc_sys_root; + +static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *); +static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); +#endif + +/* The default sysctl tables: */ + +static ctl_table root_table[] = { + { + .ctl_name = CTL_KERN, + .procname = "kernel", + .mode = 0555, + .child = kern_table, + }, + { + .ctl_name = CTL_VM, + .procname = "vm", + .mode = 0555, + .child = vm_table, + }, +#ifdef CONFIG_NET + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = net_table, + }, +#endif + { + .ctl_name = CTL_PROC, + .procname = "proc", + .mode = 0555, + .child = proc_table, + }, + { + .ctl_name = CTL_FS, + .procname = "fs", + .mode = 0555, + .child = fs_table, + }, + { + .ctl_name = CTL_DEBUG, + .procname = "debug", + .mode = 0555, + .child = debug_table, + }, + { + .ctl_name = CTL_DEV, + .procname = "dev", + .mode = 0555, + .child = dev_table, + }, + + { .ctl_name = 0 } +}; + +static ctl_table kern_table[] = { + { + .ctl_name = KERN_OSTYPE, + .procname = "ostype", + .data = system_utsname.sysname, + .maxlen = sizeof(system_utsname.sysname), + .mode = 0444, + .proc_handler = &proc_doutsstring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_OSRELEASE, + .procname = "osrelease", + .data = system_utsname.release, + .maxlen = sizeof(system_utsname.release), + .mode = 0444, + .proc_handler = &proc_doutsstring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_VERSION, + .procname = "version", + .data = system_utsname.version, + .maxlen = sizeof(system_utsname.version), + .mode = 0444, + .proc_handler = &proc_doutsstring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_NODENAME, + .procname = "hostname", + .data = system_utsname.nodename, + .maxlen = sizeof(system_utsname.nodename), + .mode = 0644, + .proc_handler = &proc_doutsstring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_DOMAINNAME, + .procname = "domainname", + .data = system_utsname.domainname, + .maxlen = sizeof(system_utsname.domainname), + .mode = 0644, + .proc_handler = &proc_doutsstring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_PANIC, + .procname = "panic", + .data = &panic_timeout, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_CORE_USES_PID, + .procname = "core_uses_pid", + .data = &core_uses_pid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_CORE_PATTERN, + .procname = "core_pattern", + .data = core_pattern, + .maxlen = 64, + .mode = 0644, + .proc_handler = &proc_dostring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_TAINTED, + .procname = "tainted", + .data = &tainted, + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_CAP_BSET, + .procname = "cap-bound", + .data = &cap_bset, + .maxlen = sizeof(kernel_cap_t), + .mode = 0600, + .proc_handler = &proc_dointvec_bset, + }, +#ifdef CONFIG_BLK_DEV_INITRD + { + .ctl_name = KERN_REALROOTDEV, + .procname = "real-root-dev", + .data = &real_root_dev, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef __sparc__ + { + .ctl_name = KERN_SPARC_REBOOT, + .procname = "reboot-cmd", + .data = reboot_command, + .maxlen = 256, + .mode = 0644, + .proc_handler = &proc_dostring, + .strategy = &sysctl_string, + }, + { + .ctl_name = KERN_SPARC_STOP_A, + .procname = "stop-a", + .data = &stop_a_enabled, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_SPARC_SCONS_PWROFF, + .procname = "scons-poweroff", + .data = &scons_pwroff, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef __hppa__ + { + .ctl_name = KERN_HPPA_PWRSW, + .procname = "soft-power", + .data = &pwrsw_enabled, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_HPPA_UNALIGNED, + .procname = "unaligned-trap", + .data = &unaligned_enabled, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif + { + .ctl_name = KERN_CTLALTDEL, + .procname = "ctrl-alt-del", + .data = &C_A_D, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_PRINTK, + .procname = "printk", + .data = &console_loglevel, + .maxlen = 4*sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#ifdef CONFIG_KMOD + { + .ctl_name = KERN_MODPROBE, + .procname = "modprobe", + .data = &modprobe_path, + .maxlen = KMOD_PATH_LEN, + .mode = 0644, + .proc_handler = &proc_dostring, + .strategy = &sysctl_string, + }, +#endif +#ifdef CONFIG_HOTPLUG + { + .ctl_name = KERN_HOTPLUG, + .procname = "hotplug", + .data = &uevent_helper, + .maxlen = UEVENT_HELPER_PATH_LEN, + .mode = 0644, + .proc_handler = &proc_dostring, + .strategy = &sysctl_string, + }, +#endif +#ifdef CONFIG_CHR_DEV_SG + { + .ctl_name = KERN_SG_BIG_BUFF, + .procname = "sg-big-buff", + .data = &sg_big_buff, + .maxlen = sizeof (int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef CONFIG_BSD_PROCESS_ACCT + { + .ctl_name = KERN_ACCT, + .procname = "acct", + .data = &acct_parm, + .maxlen = 3*sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef CONFIG_SYSVIPC + { + .ctl_name = KERN_SHMMAX, + .procname = "shmmax", + .data = &shm_ctlmax, + .maxlen = sizeof (size_t), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax, + }, + { + .ctl_name = KERN_SHMALL, + .procname = "shmall", + .data = &shm_ctlall, + .maxlen = sizeof (size_t), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax, + }, + { + .ctl_name = KERN_SHMMNI, + .procname = "shmmni", + .data = &shm_ctlmni, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_MSGMAX, + .procname = "msgmax", + .data = &msg_ctlmax, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_MSGMNI, + .procname = "msgmni", + .data = &msg_ctlmni, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_MSGMNB, + .procname = "msgmnb", + .data = &msg_ctlmnb, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_SEM, + .procname = "sem", + .data = &sem_ctls, + .maxlen = 4*sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef CONFIG_MAGIC_SYSRQ + { + .ctl_name = KERN_SYSRQ, + .procname = "sysrq", + .data = &sysrq_enabled, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif + { + .ctl_name = KERN_CADPID, + .procname = "cad_pid", + .data = &cad_pid, + .maxlen = sizeof (int), + .mode = 0600, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_MAX_THREADS, + .procname = "threads-max", + .data = &max_threads, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_RANDOM, + .procname = "random", + .mode = 0555, + .child = random_table, + }, +#ifdef CONFIG_UNIX98_PTYS + { + .ctl_name = KERN_PTY, + .procname = "pty", + .mode = 0555, + .child = pty_table, + }, +#endif + { + .ctl_name = KERN_OVERFLOWUID, + .procname = "overflowuid", + .data = &overflowuid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &minolduid, + .extra2 = &maxolduid, + }, + { + .ctl_name = KERN_OVERFLOWGID, + .procname = "overflowgid", + .data = &overflowgid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &minolduid, + .extra2 = &maxolduid, + }, +#ifdef CONFIG_S390 +#ifdef CONFIG_MATHEMU + { + .ctl_name = KERN_IEEE_EMULATION_WARNINGS, + .procname = "ieee_emulation_warnings", + .data = &sysctl_ieee_emulation_warnings, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef CONFIG_NO_IDLE_HZ + { + .ctl_name = KERN_HZ_TIMER, + .procname = "hz_timer", + .data = &sysctl_hz_timer, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif + { + .ctl_name = KERN_S390_USER_DEBUG_LOGGING, + .procname = "userprocess_debug", + .data = &sysctl_userprocess_debug, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif + { + .ctl_name = KERN_PIDMAX, + .procname = "pid_max", + .data = &pid_max, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = sysctl_intvec, + .extra1 = &pid_max_min, + .extra2 = &pid_max_max, + }, + { + .ctl_name = KERN_PANIC_ON_OOPS, + .procname = "panic_on_oops", + .data = &panic_on_oops, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_PRINTK_RATELIMIT, + .procname = "printk_ratelimit", + .data = &printk_ratelimit_jiffies, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, + { + .ctl_name = KERN_PRINTK_RATELIMIT_BURST, + .procname = "printk_ratelimit_burst", + .data = &printk_ratelimit_burst, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = KERN_NGROUPS_MAX, + .procname = "ngroups_max", + .data = &ngroups_max, + .maxlen = sizeof (int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) + { + .ctl_name = KERN_UNKNOWN_NMI_PANIC, + .procname = "unknown_nmi_panic", + .data = &unknown_nmi_panic, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_unknown_nmi_panic, + }, +#endif +#if defined(CONFIG_X86) + { + .ctl_name = KERN_BOOTLOADER_TYPE, + .procname = "bootloader_type", + .data = &bootloader_type, + .maxlen = sizeof (int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, +#endif + { + .ctl_name = KERN_RANDOMIZE, + .procname = "randomize_va_space", + .data = &randomize_va_space, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#if defined(CONFIG_S390) && defined(CONFIG_SMP) + { + .ctl_name = KERN_SPIN_RETRY, + .procname = "spin_retry", + .data = &spin_retry, + .maxlen = sizeof (int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif + { .ctl_name = 0 } +}; + +/* Constants for minimum and maximum testing in vm_table. + We use these as one-element integer vectors. */ +static int zero; +static int one_hundred = 100; + + +static ctl_table vm_table[] = { + { + .ctl_name = VM_OVERCOMMIT_MEMORY, + .procname = "overcommit_memory", + .data = &sysctl_overcommit_memory, + .maxlen = sizeof(sysctl_overcommit_memory), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = VM_OVERCOMMIT_RATIO, + .procname = "overcommit_ratio", + .data = &sysctl_overcommit_ratio, + .maxlen = sizeof(sysctl_overcommit_ratio), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = VM_PAGE_CLUSTER, + .procname = "page-cluster", + .data = &page_cluster, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = VM_DIRTY_BACKGROUND, + .procname = "dirty_background_ratio", + .data = &dirty_background_ratio, + .maxlen = sizeof(dirty_background_ratio), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero, + .extra2 = &one_hundred, + }, + { + .ctl_name = VM_DIRTY_RATIO, + .procname = "dirty_ratio", + .data = &vm_dirty_ratio, + .maxlen = sizeof(vm_dirty_ratio), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero, + .extra2 = &one_hundred, + }, + { + .ctl_name = VM_DIRTY_WB_CS, + .procname = "dirty_writeback_centisecs", + .data = &dirty_writeback_centisecs, + .maxlen = sizeof(dirty_writeback_centisecs), + .mode = 0644, + .proc_handler = &dirty_writeback_centisecs_handler, + }, + { + .ctl_name = VM_DIRTY_EXPIRE_CS, + .procname = "dirty_expire_centisecs", + .data = &dirty_expire_centisecs, + .maxlen = sizeof(dirty_expire_centisecs), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = VM_NR_PDFLUSH_THREADS, + .procname = "nr_pdflush_threads", + .data = &nr_pdflush_threads, + .maxlen = sizeof nr_pdflush_threads, + .mode = 0444 /* read-only*/, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = VM_SWAPPINESS, + .procname = "swappiness", + .data = &vm_swappiness, + .maxlen = sizeof(vm_swappiness), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero, + .extra2 = &one_hundred, + }, +#ifdef CONFIG_HUGETLB_PAGE + { + .ctl_name = VM_HUGETLB_PAGES, + .procname = "nr_hugepages", + .data = &max_huge_pages, + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = &hugetlb_sysctl_handler, + .extra1 = (void *)&hugetlb_zero, + .extra2 = (void *)&hugetlb_infinity, + }, + { + .ctl_name = VM_HUGETLB_GROUP, + .procname = "hugetlb_shm_group", + .data = &sysctl_hugetlb_shm_group, + .maxlen = sizeof(gid_t), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif + { + .ctl_name = VM_LOWMEM_RESERVE_RATIO, + .procname = "lowmem_reserve_ratio", + .data = &sysctl_lowmem_reserve_ratio, + .maxlen = sizeof(sysctl_lowmem_reserve_ratio), + .mode = 0644, + .proc_handler = &lowmem_reserve_ratio_sysctl_handler, + .strategy = &sysctl_intvec, + }, + { + .ctl_name = VM_DROP_PAGECACHE, + .procname = "drop_caches", + .data = &sysctl_drop_caches, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = drop_caches_sysctl_handler, + .strategy = &sysctl_intvec, + }, + { + .ctl_name = VM_MIN_FREE_KBYTES, + .procname = "min_free_kbytes", + .data = &min_free_kbytes, + .maxlen = sizeof(min_free_kbytes), + .mode = 0644, + .proc_handler = &min_free_kbytes_sysctl_handler, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = VM_PERCPU_PAGELIST_FRACTION, + .procname = "percpu_pagelist_fraction", + .data = &percpu_pagelist_fraction, + .maxlen = sizeof(percpu_pagelist_fraction), + .mode = 0644, + .proc_handler = &percpu_pagelist_fraction_sysctl_handler, + .strategy = &sysctl_intvec, + .extra1 = &min_percpu_pagelist_fract, + }, +#ifdef CONFIG_MMU + { + .ctl_name = VM_MAX_MAP_COUNT, + .procname = "max_map_count", + .data = &sysctl_max_map_count, + .maxlen = sizeof(sysctl_max_map_count), + .mode = 0644, + .proc_handler = &proc_dointvec + }, +#endif + { + .ctl_name = VM_LAPTOP_MODE, + .procname = "laptop_mode", + .data = &laptop_mode, + .maxlen = sizeof(laptop_mode), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = VM_BLOCK_DUMP, + .procname = "block_dump", + .data = &block_dump, + .maxlen = sizeof(block_dump), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = VM_VFS_CACHE_PRESSURE, + .procname = "vfs_cache_pressure", + .data = &sysctl_vfs_cache_pressure, + .maxlen = sizeof(sysctl_vfs_cache_pressure), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, +#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT + { + .ctl_name = VM_LEGACY_VA_LAYOUT, + .procname = "legacy_va_layout", + .data = &sysctl_legacy_va_layout, + .maxlen = sizeof(sysctl_legacy_va_layout), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, +#endif +#ifdef CONFIG_SWAP + { + .ctl_name = VM_SWAP_TOKEN_TIMEOUT, + .procname = "swap_token_timeout", + .data = &swap_token_default_timeout, + .maxlen = sizeof(swap_token_default_timeout), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, +#endif +#ifdef CONFIG_NUMA + { + .ctl_name = VM_ZONE_RECLAIM_MODE, + .procname = "zone_reclaim_mode", + .data = &zone_reclaim_mode, + .maxlen = sizeof(zone_reclaim_mode), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = VM_ZONE_RECLAIM_INTERVAL, + .procname = "zone_reclaim_interval", + .data = &zone_reclaim_interval, + .maxlen = sizeof(zone_reclaim_interval), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, +#endif + { .ctl_name = 0 } +}; + +static ctl_table proc_table[] = { + { .ctl_name = 0 } +}; + +static ctl_table fs_table[] = { + { + .ctl_name = FS_NRINODE, + .procname = "inode-nr", + .data = &inodes_stat, + .maxlen = 2*sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = FS_STATINODE, + .procname = "inode-state", + .data = &inodes_stat, + .maxlen = 7*sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = FS_NRFILE, + .procname = "file-nr", + .data = &files_stat, + .maxlen = 3*sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = FS_MAXFILE, + .procname = "file-max", + .data = &files_stat.max_files, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = FS_DENTRY, + .procname = "dentry-state", + .data = &dentry_stat, + .maxlen = 6*sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = FS_OVERFLOWUID, + .procname = "overflowuid", + .data = &fs_overflowuid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &minolduid, + .extra2 = &maxolduid, + }, + { + .ctl_name = FS_OVERFLOWGID, + .procname = "overflowgid", + .data = &fs_overflowgid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &minolduid, + .extra2 = &maxolduid, + }, + { + .ctl_name = FS_LEASES, + .procname = "leases-enable", + .data = &leases_enable, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#ifdef CONFIG_DNOTIFY + { + .ctl_name = FS_DIR_NOTIFY, + .procname = "dir-notify-enable", + .data = &dir_notify_enable, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, +#endif +#ifdef CONFIG_MMU + { + .ctl_name = FS_LEASE_TIME, + .procname = "lease-break-time", + .data = &lease_break_time, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = FS_AIO_NR, + .procname = "aio-nr", + .data = &aio_nr, + .maxlen = sizeof(aio_nr), + .mode = 0444, + .proc_handler = &proc_doulongvec_minmax, + }, + { + .ctl_name = FS_AIO_MAX_NR, + .procname = "aio-max-nr", + .data = &aio_max_nr, + .maxlen = sizeof(aio_max_nr), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax, + }, +#ifdef CONFIG_INOTIFY + { + .ctl_name = FS_INOTIFY, + .procname = "inotify", + .mode = 0555, + .child = inotify_table, + }, +#endif +#endif + { + .ctl_name = KERN_SETUID_DUMPABLE, + .procname = "suid_dumpable", + .data = &suid_dumpable, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = 0 } +}; + +static ctl_table debug_table[] = { + { .ctl_name = 0 } +}; + +static ctl_table dev_table[] = { + { .ctl_name = 0 } +}; + +extern void init_irq_proc (void); + +static DEFINE_SPINLOCK(sysctl_lock); + +/* called under sysctl_lock */ +static int use_table(struct ctl_table_header *p) +{ + if (unlikely(p->unregistering)) + return 0; + p->used++; + return 1; +} + +/* called under sysctl_lock */ +static void unuse_table(struct ctl_table_header *p) +{ + if (!--p->used) + if (unlikely(p->unregistering)) + complete(p->unregistering); +} + +/* called under sysctl_lock, will reacquire if has to wait */ +static void start_unregistering(struct ctl_table_header *p) +{ + /* + * if p->used is 0, nobody will ever touch that entry again; + * we'll eliminate all paths to it before dropping sysctl_lock + */ + if (unlikely(p->used)) { + struct completion wait; + init_completion(&wait); + p->unregistering = &wait; + spin_unlock(&sysctl_lock); + wait_for_completion(&wait); + spin_lock(&sysctl_lock); + } + /* + * do not remove from the list until nobody holds it; walking the + * list in do_sysctl() relies on that. + */ + list_del_init(&p->ctl_entry); +} + +void __init sysctl_init(void) +{ +#ifdef CONFIG_PROC_FS + register_proc_table(root_table, proc_sys_root, &root_table_header); + init_irq_proc(); +#endif +} + +int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen) +{ + struct list_head *tmp; + int error = -ENOTDIR; + + if (nlen <= 0 || nlen >= CTL_MAXNAME) + return -ENOTDIR; + if (oldval) { + int old_len; + if (!oldlenp || get_user(old_len, oldlenp)) + return -EFAULT; + } + spin_lock(&sysctl_lock); + tmp = &root_table_header.ctl_entry; + do { + struct ctl_table_header *head = + list_entry(tmp, struct ctl_table_header, ctl_entry); + void *context = NULL; + + if (!use_table(head)) + continue; + + spin_unlock(&sysctl_lock); + + error = parse_table(name, nlen, oldval, oldlenp, + newval, newlen, head->ctl_table, + &context); + kfree(context); + + spin_lock(&sysctl_lock); + unuse_table(head); + if (error != -ENOTDIR) + break; + } while ((tmp = tmp->next) != &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); + return error; +} + +asmlinkage long sys_sysctl(struct __sysctl_args __user *args) +{ + struct __sysctl_args tmp; + int error; + + if (copy_from_user(&tmp, args, sizeof(tmp))) + return -EFAULT; + + lock_kernel(); + error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp, + tmp.newval, tmp.newlen); + unlock_kernel(); + return error; +} + +/* + * ctl_perm does NOT grant the superuser all rights automatically, because + * some sysctl variables are readonly even to root. + */ + +static int test_perm(int mode, int op) +{ + if (!current->euid) + mode >>= 6; + else if (in_egroup_p(0)) + mode >>= 3; + if ((mode & op & 0007) == op) + return 0; + return -EACCES; +} + +static inline int ctl_perm(ctl_table *table, int op) +{ + int error; + error = security_sysctl(table, op); + if (error) + return error; + return test_perm(table->mode, op); +} + +static int parse_table(int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, + ctl_table *table, void **context) +{ + int n; +repeat: + if (!nlen) + return -ENOTDIR; + if (get_user(n, name)) + return -EFAULT; + for ( ; table->ctl_name; table++) { + if (n == table->ctl_name || table->ctl_name == CTL_ANY) { + int error; + if (table->child) { + if (ctl_perm(table, 001)) + return -EPERM; + if (table->strategy) { + error = table->strategy( + table, name, nlen, + oldval, oldlenp, + newval, newlen, context); + if (error) + return error; + } + name++; + nlen--; + table = table->child; + goto repeat; + } + error = do_sysctl_strategy(table, name, nlen, + oldval, oldlenp, + newval, newlen, context); + return error; + } + } + return -ENOTDIR; +} + +/* Perform the actual read/write of a sysctl table entry. */ +int do_sysctl_strategy (ctl_table *table, + int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + int op = 0, rc; + size_t len; + + if (oldval) + op |= 004; + if (newval) + op |= 002; + if (ctl_perm(table, op)) + return -EPERM; + + if (table->strategy) { + rc = table->strategy(table, name, nlen, oldval, oldlenp, + newval, newlen, context); + if (rc < 0) + return rc; + if (rc > 0) + return 0; + } + + /* If there is no strategy routine, or if the strategy returns + * zero, proceed with automatic r/w */ + if (table->data && table->maxlen) { + if (oldval && oldlenp) { + if (get_user(len, oldlenp)) + return -EFAULT; + if (len) { + if (len > table->maxlen) + len = table->maxlen; + if(copy_to_user(oldval, table->data, len)) + return -EFAULT; + if(put_user(len, oldlenp)) + return -EFAULT; + } + } + if (newval && newlen) { + len = newlen; + if (len > table->maxlen) + len = table->maxlen; + if(copy_from_user(table->data, newval, len)) + return -EFAULT; + } + } + return 0; +} + +/** + * register_sysctl_table - register a sysctl hierarchy + * @table: the top-level table structure + * @insert_at_head: whether the entry should be inserted in front or at the end + * + * Register a sysctl table hierarchy. @table should be a filled in ctl_table + * array. An entry with a ctl_name of 0 terminates the table. + * + * The members of the &ctl_table structure are used as follows: + * + * ctl_name - This is the numeric sysctl value used by sysctl(2). The number + * must be unique within that level of sysctl + * + * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not + * enter a sysctl file + * + * data - a pointer to data for use by proc_handler + * + * maxlen - the maximum size in bytes of the data + * + * mode - the file permissions for the /proc/sys file, and for sysctl(2) + * + * child - a pointer to the child sysctl table if this entry is a directory, or + * %NULL. + * + * proc_handler - the text handler routine (described below) + * + * strategy - the strategy routine (described below) + * + * de - for internal use by the sysctl routines + * + * extra1, extra2 - extra pointers usable by the proc handler routines + * + * Leaf nodes in the sysctl tree will be represented by a single file + * under /proc; non-leaf nodes will be represented by directories. + * + * sysctl(2) can automatically manage read and write requests through + * the sysctl table. The data and maxlen fields of the ctl_table + * struct enable minimal validation of the values being written to be + * performed, and the mode field allows minimal authentication. + * + * More sophisticated management can be enabled by the provision of a + * strategy routine with the table entry. This will be called before + * any automatic read or write of the data is performed. + * + * The strategy routine may return + * + * < 0 - Error occurred (error is passed to user process) + * + * 0 - OK - proceed with automatic read or write. + * + * > 0 - OK - read or write has been done by the strategy routine, so + * return immediately. + * + * There must be a proc_handler routine for any terminal nodes + * mirrored under /proc/sys (non-terminals are handled by a built-in + * directory handler). Several default handlers are available to + * cover common cases - + * + * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(), + * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(), + * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax() + * + * It is the handler's job to read the input buffer from user memory + * and process it. The handler should return 0 on success. + * + * This routine returns %NULL on a failure to register, and a pointer + * to the table header on success. + */ +struct ctl_table_header *register_sysctl_table(ctl_table * table, + int insert_at_head) +{ + struct ctl_table_header *tmp; + tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL); + if (!tmp) + return NULL; + tmp->ctl_table = table; + INIT_LIST_HEAD(&tmp->ctl_entry); + tmp->used = 0; + tmp->unregistering = NULL; + spin_lock(&sysctl_lock); + if (insert_at_head) + list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); + else + list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); +#ifdef CONFIG_PROC_FS + register_proc_table(table, proc_sys_root, tmp); +#endif + return tmp; +} + +/** + * unregister_sysctl_table - unregister a sysctl table hierarchy + * @header: the header returned from register_sysctl_table + * + * Unregisters the sysctl table and all children. proc entries may not + * actually be removed until they are no longer used by anyone. + */ +void unregister_sysctl_table(struct ctl_table_header * header) +{ + might_sleep(); + spin_lock(&sysctl_lock); + start_unregistering(header); +#ifdef CONFIG_PROC_FS + unregister_proc_table(header->ctl_table, proc_sys_root); +#endif + spin_unlock(&sysctl_lock); + kfree(header); +} + +/* + * /proc/sys support + */ + +#ifdef CONFIG_PROC_FS + +/* Scan the sysctl entries in table and add them all into /proc */ +static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) +{ + struct proc_dir_entry *de; + int len; + mode_t mode; + + for (; table->ctl_name; table++) { + /* Can't do anything without a proc name. */ + if (!table->procname) + continue; + /* Maybe we can't do anything with it... */ + if (!table->proc_handler && !table->child) { + printk(KERN_WARNING "SYSCTL: Can't register %s\n", + table->procname); + continue; + } + + len = strlen(table->procname); + mode = table->mode; + + de = NULL; + if (table->proc_handler) + mode |= S_IFREG; + else { + mode |= S_IFDIR; + for (de = root->subdir; de; de = de->next) { + if (proc_match(len, table->procname, de)) + break; + } + /* If the subdir exists already, de is non-NULL */ + } + + if (!de) { + de = create_proc_entry(table->procname, mode, root); + if (!de) + continue; + de->set = set; + de->data = (void *) table; + if (table->proc_handler) + de->proc_fops = &proc_sys_file_operations; + } + table->de = de; + if (de->mode & S_IFDIR) + register_proc_table(table->child, de, set); + } +} + +/* + * Unregister a /proc sysctl table and any subdirectories. + */ +static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root) +{ + struct proc_dir_entry *de; + for (; table->ctl_name; table++) { + if (!(de = table->de)) + continue; + if (de->mode & S_IFDIR) { + if (!table->child) { + printk (KERN_ALERT "Help - malformed sysctl tree on free\n"); + continue; + } + unregister_proc_table(table->child, de); + + /* Don't unregister directories which still have entries.. */ + if (de->subdir) + continue; + } + + /* + * In any case, mark the entry as goner; we'll keep it + * around if it's busy, but we'll know to do nothing with + * its fields. We are under sysctl_lock here. + */ + de->data = NULL; + + /* Don't unregister proc entries that are still being used.. */ + if (atomic_read(&de->count)) + continue; + + table->de = NULL; + remove_proc_entry(table->procname, root); + } +} + +static ssize_t do_rw_proc(int write, struct file * file, char __user * buf, + size_t count, loff_t *ppos) +{ + int op; + struct proc_dir_entry *de = PDE(file->f_dentry->d_inode); + struct ctl_table *table; + size_t res; + ssize_t error = -ENOTDIR; + + spin_lock(&sysctl_lock); + if (de && de->data && use_table(de->set)) { + /* + * at that point we know that sysctl was not unregistered + * and won't be until we finish + */ + spin_unlock(&sysctl_lock); + table = (struct ctl_table *) de->data; + if (!table || !table->proc_handler) + goto out; + error = -EPERM; + op = (write ? 002 : 004); + if (ctl_perm(table, op)) + goto out; + + /* careful: calling conventions are nasty here */ + res = count; + error = (*table->proc_handler)(table, write, file, + buf, &res, ppos); + if (!error) + error = res; + out: + spin_lock(&sysctl_lock); + unuse_table(de->set); + } + spin_unlock(&sysctl_lock); + return error; +} + +static int proc_opensys(struct inode *inode, struct file *file) +{ + if (file->f_mode & FMODE_WRITE) { + /* + * sysctl entries that are not writable, + * are _NOT_ writable, capabilities or not. + */ + if (!(inode->i_mode & S_IWUSR)) + return -EPERM; + } + + return 0; +} + +static ssize_t proc_readsys(struct file * file, char __user * buf, + size_t count, loff_t *ppos) +{ + return do_rw_proc(0, file, buf, count, ppos); +} + +static ssize_t proc_writesys(struct file * file, const char __user * buf, + size_t count, loff_t *ppos) +{ + return do_rw_proc(1, file, (char __user *) buf, count, ppos); +} + +/** + * proc_dostring - read a string sysctl + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes a string from/to the user buffer. If the kernel + * buffer provided is not large enough to hold the string, the + * string is truncated. The copied string is %NULL-terminated. + * If the string is being read by the user process, it is copied + * and a newline '\n' is added. It is truncated if the buffer is + * not large enough. + * + * Returns 0 on success. + */ +int proc_dostring(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + size_t len; + char __user *p; + char c; + + if (!table->data || !table->maxlen || !*lenp || + (*ppos && !write)) { + *lenp = 0; + return 0; + } + + if (write) { + len = 0; + p = buffer; + while (len < *lenp) { + if (get_user(c, p++)) + return -EFAULT; + if (c == 0 || c == '\n') + break; + len++; + } + if (len >= table->maxlen) + len = table->maxlen-1; + if(copy_from_user(table->data, buffer, len)) + return -EFAULT; + ((char *) table->data)[len] = 0; + *ppos += *lenp; + } else { + len = strlen(table->data); + if (len > table->maxlen) + len = table->maxlen; + if (len > *lenp) + len = *lenp; + if (len) + if(copy_to_user(buffer, table->data, len)) + return -EFAULT; + if (len < *lenp) { + if(put_user('\n', ((char __user *) buffer) + len)) + return -EFAULT; + len++; + } + *lenp = len; + *ppos += len; + } + return 0; +} + +/* + * Special case of dostring for the UTS structure. This has locks + * to observe. Should this be in kernel/sys.c ???? + */ + +static int proc_doutsstring(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int r; + + if (!write) { + down_read(&uts_sem); + r=proc_dostring(table,0,filp,buffer,lenp, ppos); + up_read(&uts_sem); + } else { + down_write(&uts_sem); + r=proc_dostring(table,1,filp,buffer,lenp, ppos); + up_write(&uts_sem); + } + return r; +} + +static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp, + int *valp, + int write, void *data) +{ + if (write) { + *valp = *negp ? -*lvalp : *lvalp; + } else { + int val = *valp; + if (val < 0) { + *negp = -1; + *lvalp = (unsigned long)-val; + } else { + *negp = 0; + *lvalp = (unsigned long)val; + } + } + return 0; +} + +static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos, + int (*conv)(int *negp, unsigned long *lvalp, int *valp, + int write, void *data), + void *data) +{ +#define TMPBUFLEN 21 + int *i, vleft, first=1, neg, val; + unsigned long lval; + size_t left, len; + + char buf[TMPBUFLEN], *p; + char __user *s = buffer; + + if (!table->data || !table->maxlen || !*lenp || + (*ppos && !write)) { + *lenp = 0; + return 0; + } + + i = (int *) table->data; + vleft = table->maxlen / sizeof(*i); + left = *lenp; + + if (!conv) + conv = do_proc_dointvec_conv; + + for (; left && vleft--; i++, first=0) { + if (write) { + while (left) { + char c; + if (get_user(c, s)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + s++; + } + if (!left) + break; + neg = 0; + len = left; + if (len > sizeof(buf) - 1) + len = sizeof(buf) - 1; + if (copy_from_user(buf, s, len)) + return -EFAULT; + buf[len] = 0; + p = buf; + if (*p == '-' && left > 1) { + neg = 1; + left--, p++; + } + if (*p < '0' || *p > '9') + break; + + lval = simple_strtoul(p, &p, 0); + + len = p-buf; + if ((len < left) && *p && !isspace(*p)) + break; + if (neg) + val = -val; + s += len; + left -= len; + + if (conv(&neg, &lval, i, 1, data)) + break; + } else { + p = buf; + if (!first) + *p++ = '\t'; + + if (conv(&neg, &lval, i, 0, data)) + break; + + sprintf(p, "%s%lu", neg ? "-" : "", lval); + len = strlen(buf); + if (len > left) + len = left; + if(copy_to_user(s, buf, len)) + return -EFAULT; + left -= len; + s += len; + } + } + + if (!write && !first && left) { + if(put_user('\n', s)) + return -EFAULT; + left--, s++; + } + if (write) { + while (left) { + char c; + if (get_user(c, s++)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + } + } + if (write && first) + return -EINVAL; + *lenp -= left; + *ppos += *lenp; + return 0; +#undef TMPBUFLEN +} + +/** + * proc_dointvec - read a vector of integers + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned int) integer + * values from/to the user buffer, treated as an ASCII string. + * + * Returns 0 on success. + */ +int proc_dointvec(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, + NULL,NULL); +} + +#define OP_SET 0 +#define OP_AND 1 +#define OP_OR 2 +#define OP_MAX 3 +#define OP_MIN 4 + +static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp, + int *valp, + int write, void *data) +{ + int op = *(int *)data; + if (write) { + int val = *negp ? -*lvalp : *lvalp; + switch(op) { + case OP_SET: *valp = val; break; + case OP_AND: *valp &= val; break; + case OP_OR: *valp |= val; break; + case OP_MAX: if(*valp < val) + *valp = val; + break; + case OP_MIN: if(*valp > val) + *valp = val; + break; + } + } else { + int val = *valp; + if (val < 0) { + *negp = -1; + *lvalp = (unsigned long)-val; + } else { + *negp = 0; + *lvalp = (unsigned long)val; + } + } + return 0; +} + +/* + * init may raise the set. + */ + +int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int op; + + if (!capable(CAP_SYS_MODULE)) { + return -EPERM; + } + + op = (current->pid == 1) ? OP_SET : OP_AND; + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, + do_proc_dointvec_bset_conv,&op); +} + +struct do_proc_dointvec_minmax_conv_param { + int *min; + int *max; +}; + +static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, + int *valp, + int write, void *data) +{ + struct do_proc_dointvec_minmax_conv_param *param = data; + if (write) { + int val = *negp ? -*lvalp : *lvalp; + if ((param->min && *param->min > val) || + (param->max && *param->max < val)) + return -EINVAL; + *valp = val; + } else { + int val = *valp; + if (val < 0) { + *negp = -1; + *lvalp = (unsigned long)-val; + } else { + *negp = 0; + *lvalp = (unsigned long)val; + } + } + return 0; +} + +/** + * proc_dointvec_minmax - read a vector of integers with min/max values + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned int) integer + * values from/to the user buffer, treated as an ASCII string. + * + * This routine will ensure the values are within the range specified by + * table->extra1 (min) and table->extra2 (max). + * + * Returns 0 on success. + */ +int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct do_proc_dointvec_minmax_conv_param param = { + .min = (int *) table->extra1, + .max = (int *) table->extra2, + }; + return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, + do_proc_dointvec_minmax_conv, ¶m); +} + +static int do_proc_doulongvec_minmax(ctl_table *table, int write, + struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos, + unsigned long convmul, + unsigned long convdiv) +{ +#define TMPBUFLEN 21 + unsigned long *i, *min, *max, val; + int vleft, first=1, neg; + size_t len, left; + char buf[TMPBUFLEN], *p; + char __user *s = buffer; + + if (!table->data || !table->maxlen || !*lenp || + (*ppos && !write)) { + *lenp = 0; + return 0; + } + + i = (unsigned long *) table->data; + min = (unsigned long *) table->extra1; + max = (unsigned long *) table->extra2; + vleft = table->maxlen / sizeof(unsigned long); + left = *lenp; + + for (; left && vleft--; i++, min++, max++, first=0) { + if (write) { + while (left) { + char c; + if (get_user(c, s)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + s++; + } + if (!left) + break; + neg = 0; + len = left; + if (len > TMPBUFLEN-1) + len = TMPBUFLEN-1; + if (copy_from_user(buf, s, len)) + return -EFAULT; + buf[len] = 0; + p = buf; + if (*p == '-' && left > 1) { + neg = 1; + left--, p++; + } + if (*p < '0' || *p > '9') + break; + val = simple_strtoul(p, &p, 0) * convmul / convdiv ; + len = p-buf; + if ((len < left) && *p && !isspace(*p)) + break; + if (neg) + val = -val; + s += len; + left -= len; + + if(neg) + continue; + if ((min && val < *min) || (max && val > *max)) + continue; + *i = val; + } else { + p = buf; + if (!first) + *p++ = '\t'; + sprintf(p, "%lu", convdiv * (*i) / convmul); + len = strlen(buf); + if (len > left) + len = left; + if(copy_to_user(s, buf, len)) + return -EFAULT; + left -= len; + s += len; + } + } + + if (!write && !first && left) { + if(put_user('\n', s)) + return -EFAULT; + left--, s++; + } + if (write) { + while (left) { + char c; + if (get_user(c, s++)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + } + } + if (write && first) + return -EINVAL; + *lenp -= left; + *ppos += *lenp; + return 0; +#undef TMPBUFLEN +} + +/** + * proc_doulongvec_minmax - read a vector of long integers with min/max values + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long + * values from/to the user buffer, treated as an ASCII string. + * + * This routine will ensure the values are within the range specified by + * table->extra1 (min) and table->extra2 (max). + * + * Returns 0 on success. + */ +int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l); +} + +/** + * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long + * values from/to the user buffer, treated as an ASCII string. The values + * are treated as milliseconds, and converted to jiffies when they are stored. + * + * This routine will ensure the values are within the range specified by + * table->extra1 (min) and table->extra2 (max). + * + * Returns 0 on success. + */ +int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, + struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + return do_proc_doulongvec_minmax(table, write, filp, buffer, + lenp, ppos, HZ, 1000l); +} + + +static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp, + int *valp, + int write, void *data) +{ + if (write) { + *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ); + } else { + int val = *valp; + unsigned long lval; + if (val < 0) { + *negp = -1; + lval = (unsigned long)-val; + } else { + *negp = 0; + lval = (unsigned long)val; + } + *lvalp = lval / HZ; + } + return 0; +} + +static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp, + int *valp, + int write, void *data) +{ + if (write) { + *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp); + } else { + int val = *valp; + unsigned long lval; + if (val < 0) { + *negp = -1; + lval = (unsigned long)-val; + } else { + *negp = 0; + lval = (unsigned long)val; + } + *lvalp = jiffies_to_clock_t(lval); + } + return 0; +} + +static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp, + int *valp, + int write, void *data) +{ + if (write) { + *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp); + } else { + int val = *valp; + unsigned long lval; + if (val < 0) { + *negp = -1; + lval = (unsigned long)-val; + } else { + *negp = 0; + lval = (unsigned long)val; + } + *lvalp = jiffies_to_msecs(lval); + } + return 0; +} + +/** + * proc_dointvec_jiffies - read a vector of integers as seconds + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned int) integer + * values from/to the user buffer, treated as an ASCII string. + * The values read are assumed to be in seconds, and are converted into + * jiffies. + * + * Returns 0 on success. + */ +int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, + do_proc_dointvec_jiffies_conv,NULL); +} + +/** + * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: pointer to the file position + * + * Reads/writes up to table->maxlen/sizeof(unsigned int) integer + * values from/to the user buffer, treated as an ASCII string. + * The values read are assumed to be in 1/USER_HZ seconds, and + * are converted into jiffies. + * + * Returns 0 on success. + */ +int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, + do_proc_dointvec_userhz_jiffies_conv,NULL); +} + +/** + * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds + * @table: the sysctl table + * @write: %TRUE if this is a write to the sysctl file + * @filp: the file structure + * @buffer: the user buffer + * @lenp: the size of the user buffer + * @ppos: file position + * @ppos: the current position in the file + * + * Reads/writes up to table->maxlen/sizeof(unsigned int) integer + * values from/to the user buffer, treated as an ASCII string. + * The values read are assumed to be in 1/1000 seconds, and + * are converted into jiffies. + * + * Returns 0 on success. + */ +int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, + do_proc_dointvec_ms_jiffies_conv, NULL); +} + +#else /* CONFIG_PROC_FS */ + +int proc_dostring(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +static int proc_doutsstring(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, + struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + + +#endif /* CONFIG_PROC_FS */ + + +/* + * General sysctl support routines + */ + +/* The generic string strategy routine: */ +int sysctl_string(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + if (!table->data || !table->maxlen) + return -ENOTDIR; + + if (oldval && oldlenp) { + size_t bufsize; + if (get_user(bufsize, oldlenp)) + return -EFAULT; + if (bufsize) { + size_t len = strlen(table->data), copied; + + /* This shouldn't trigger for a well-formed sysctl */ + if (len > table->maxlen) + len = table->maxlen; + + /* Copy up to a max of bufsize-1 bytes of the string */ + copied = (len >= bufsize) ? bufsize - 1 : len; + + if (copy_to_user(oldval, table->data, copied) || + put_user(0, (char __user *)(oldval + copied))) + return -EFAULT; + if (put_user(len, oldlenp)) + return -EFAULT; + } + } + if (newval && newlen) { + size_t len = newlen; + if (len > table->maxlen) + len = table->maxlen; + if(copy_from_user(table->data, newval, len)) + return -EFAULT; + if (len == table->maxlen) + len--; + ((char *) table->data)[len] = 0; + } + return 1; +} + +/* + * This function makes sure that all of the integers in the vector + * are between the minimum and maximum values given in the arrays + * table->extra1 and table->extra2, respectively. + */ +int sysctl_intvec(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + + if (newval && newlen) { + int __user *vec = (int __user *) newval; + int *min = (int *) table->extra1; + int *max = (int *) table->extra2; + size_t length; + int i; + + if (newlen % sizeof(int) != 0) + return -EINVAL; + + if (!table->extra1 && !table->extra2) + return 0; + + if (newlen > table->maxlen) + newlen = table->maxlen; + length = newlen / sizeof(int); + + for (i = 0; i < length; i++) { + int value; + if (get_user(value, vec + i)) + return -EFAULT; + if (min && value < min[i]) + return -EINVAL; + if (max && value > max[i]) + return -EINVAL; + } + } + return 0; +} + +/* Strategy function to convert jiffies to seconds */ +int sysctl_jiffies(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + if (oldval) { + size_t olen; + if (oldlenp) { + if (get_user(olen, oldlenp)) + return -EFAULT; + if (olen!=sizeof(int)) + return -EINVAL; + } + if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) || + (oldlenp && put_user(sizeof(int),oldlenp))) + return -EFAULT; + } + if (newval && newlen) { + int new; + if (newlen != sizeof(int)) + return -EINVAL; + if (get_user(new, (int __user *)newval)) + return -EFAULT; + *(int *)(table->data) = new*HZ; + } + return 1; +} + +/* Strategy function to convert jiffies to seconds */ +int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + if (oldval) { + size_t olen; + if (oldlenp) { + if (get_user(olen, oldlenp)) + return -EFAULT; + if (olen!=sizeof(int)) + return -EINVAL; + } + if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) || + (oldlenp && put_user(sizeof(int),oldlenp))) + return -EFAULT; + } + if (newval && newlen) { + int new; + if (newlen != sizeof(int)) + return -EINVAL; + if (get_user(new, (int __user *)newval)) + return -EFAULT; + *(int *)(table->data) = msecs_to_jiffies(new); + } + return 1; +} + +#else /* CONFIG_SYSCTL */ + + +asmlinkage long sys_sysctl(struct __sysctl_args __user *args) +{ + return -ENOSYS; +} + +int sysctl_string(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + return -ENOSYS; +} + +int sysctl_intvec(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + return -ENOSYS; +} + +int sysctl_jiffies(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + return -ENOSYS; +} + +int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) +{ + return -ENOSYS; +} + +int proc_dostring(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, + struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} + +struct ctl_table_header * register_sysctl_table(ctl_table * table, + int insert_at_head) +{ + return NULL; +} + +void unregister_sysctl_table(struct ctl_table_header * table) +{ +} + +#endif /* CONFIG_SYSCTL */ + +/* + * No sense putting this after each symbol definition, twice, + * exception granted :-) + */ +EXPORT_SYMBOL(proc_dointvec); +EXPORT_SYMBOL(proc_dointvec_jiffies); +EXPORT_SYMBOL(proc_dointvec_minmax); +EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); +EXPORT_SYMBOL(proc_dointvec_ms_jiffies); +EXPORT_SYMBOL(proc_dostring); +EXPORT_SYMBOL(proc_doulongvec_minmax); +EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); +EXPORT_SYMBOL(register_sysctl_table); +EXPORT_SYMBOL(sysctl_intvec); +EXPORT_SYMBOL(sysctl_jiffies); +EXPORT_SYMBOL(sysctl_ms_jiffies); +EXPORT_SYMBOL(sysctl_string); +EXPORT_SYMBOL(unregister_sysctl_table);