diff --git a/[refs] b/[refs] index d6b2b5c5749d..5eb7faf07ce6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 068345f4a873e8b0b511e8f94a595a20e176eeff +refs/heads/master: 088eec1192a0ae60fc218796027e622008af36c0 diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index 46bcff2849bd..8c5698a8c2e1 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -643,60 +643,6 @@ X!Idrivers/video/console/fonts.c !Edrivers/spi/spi.c - - I<superscript>2</superscript>C and SMBus Subsystem - - - I2C (or without fancy typography, "I2C") - is an acronym for the "Inter-IC" bus, a simple bus protocol which is - widely used where low data rate communications suffice. - Since it's also a licensed trademark, some vendors use another - name (such as "Two-Wire Interface", TWI) for the same bus. - I2C only needs two signals (SCL for clock, SDA for data), conserving - board real estate and minimizing signal quality issues. - Most I2C devices use seven bit addresses, and bus speeds of up - to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet - found wide use. - I2C is a multi-master bus; open drain signaling is used to - arbitrate between masters, as well as to handshake and to - synchronize clocks from slower clients. - - - - The Linux I2C programming interfaces support only the master - side of bus interactions, not the slave side. - The programming interface is structured around two kinds of driver, - and two kinds of device. - An I2C "Adapter Driver" abstracts the controller hardware; it binds - to a physical device (perhaps a PCI device or platform_device) and - exposes a struct i2c_adapter representing - each I2C bus segment it manages. - On each I2C bus segment will be I2C devices represented by a - struct i2c_client. Those devices will - be bound to a struct i2c_driver, - which should follow the standard Linux driver model. - (At this writing, a legacy model is more widely used.) - There are functions to perform various I2C protocol operations; at - this writing all such functions are usable only from task context. - - - - The System Management Bus (SMBus) is a sibling protocol. Most SMBus - systems are also I2C conformant. The electrical constraints are - tighter for SMBus, and it standardizes particular protocol messages - and idioms. Controllers that support I2C can also support most - SMBus operations, but SMBus controllers don't support all the protocol - options that an I2C controller will. - There are functions to perform various SMBus protocol operations, - either using I2C primitives or by issuing SMBus commands to - i2c_adapter devices which don't support those I2C operations. - - -!Iinclude/linux/i2c.h -!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info -!Edrivers/i2c/i2c-core.c - - splice API ) @@ -708,5 +654,4 @@ X!Idrivers/video/console/fonts.c !Ffs/splice.c - diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 281458b47d75..3a159dac04f5 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -330,10 +330,3 @@ Who: Tejun Heo --------------------------- -What: Legacy RTC drivers (under drivers/i2c/chips) -When: November 2007 -Why: Obsolete. We have a RTC subsystem with better drivers. -Who: Jean Delvare - ---------------------------- - diff --git a/trunk/Documentation/i2c/busses/i2c-i801 b/trunk/Documentation/i2c/busses/i2c-i801 index fe6406f2f9a6..c34f0db78a30 100644 --- a/trunk/Documentation/i2c/busses/i2c-i801 +++ b/trunk/Documentation/i2c/busses/i2c-i801 @@ -5,8 +5,8 @@ Supported adapters: '810' and '810E' chipsets) * Intel 82801BA (ICH2 - part of the '815E' chipset) * Intel 82801CA/CAM (ICH3) - * Intel 82801DB (ICH4) (HW PEC supported) - * Intel 82801EB/ER (ICH5) (HW PEC supported) + * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported) + * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported) * Intel 6300ESB * Intel 82801FB/FR/FW/FRW (ICH6) * Intel 82801G (ICH7) diff --git a/trunk/Documentation/i2c/busses/i2c-piix4 b/trunk/Documentation/i2c/busses/i2c-piix4 index fa0c786a8bf5..7cbe43fa2701 100644 --- a/trunk/Documentation/i2c/busses/i2c-piix4 +++ b/trunk/Documentation/i2c/busses/i2c-piix4 @@ -6,7 +6,7 @@ Supported adapters: Datasheet: Publicly available at the Intel website * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks - * ATI IXP200, IXP300, IXP400, SB600 and SB700 southbridges + * ATI IXP200, IXP300, IXP400 and SB600 southbridges Datasheet: Not publicly available * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com diff --git a/trunk/Documentation/i2c/busses/i2c-taos-evm b/trunk/Documentation/i2c/busses/i2c-taos-evm deleted file mode 100644 index 9146e33be6dd..000000000000 --- a/trunk/Documentation/i2c/busses/i2c-taos-evm +++ /dev/null @@ -1,46 +0,0 @@ -Kernel driver i2c-taos-evm - -Author: Jean Delvare - -This is a driver for the evaluation modules for TAOS I2C/SMBus chips. -The modules include an SMBus master with limited capabilities, which can -be controlled over the serial port. Virtually all evaluation modules -are supported, but a few lines of code need to be added for each new -module to instantiate the right I2C chip on the bus. Obviously, a driver -for the chip in question is also needed. - -Currently supported devices are: - -* TAOS TSL2550 EVM - -For addtional information on TAOS products, please see - http://www.taosinc.com/ - - -Using this driver ------------------ - -In order to use this driver, you'll need the serport driver, and the -inputattach tool, which is part of the input-utils package. The following -commands will tell the kernel that you have a TAOS EVM on the first -serial port: - -# modprobe serport -# inputattach --taos-evm /dev/ttyS0 - - -Technical details ------------------ - -Only 4 SMBus transaction types are supported by the TAOS evaluation -modules: -* Receive Byte -* Send Byte -* Read Byte -* Write Byte - -The communication protocol is text-based and pretty simple. It is -described in a PDF document on the CD which comes with the evaluation -module. The communication is rather slow, because the serial port has -to operate at 1200 bps. However, I don't think this is a big concern in -practice, as these modules are meant for evaluation and testing only. diff --git a/trunk/Documentation/i2c/chips/max6875 b/trunk/Documentation/i2c/chips/max6875 index a0cd8af2f408..96fec562a8e9 100644 --- a/trunk/Documentation/i2c/chips/max6875 +++ b/trunk/Documentation/i2c/chips/max6875 @@ -99,7 +99,7 @@ And then read the data or - count = i2c_smbus_read_i2c_block_data(fd, 0x84, 16, buffer); + count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer); The block read should read 16 bytes. 0x84 is the block read command. diff --git a/trunk/Documentation/i2c/chips/x1205 b/trunk/Documentation/i2c/chips/x1205 new file mode 100644 index 000000000000..09407c991fe5 --- /dev/null +++ b/trunk/Documentation/i2c/chips/x1205 @@ -0,0 +1,38 @@ +Kernel driver x1205 +=================== + +Supported chips: + * Xicor X1205 RTC + Prefix: 'x1205' + Addresses scanned: none + Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html + +Authors: + Karen Spearel , + Alessandro Zummo + +Description +----------- + +This module aims to provide complete access to the Xicor X1205 RTC. +Recently Xicor has merged with Intersil, but the chip is +still sold under the Xicor brand. + +This chip is located at address 0x6f and uses a 2-byte register addressing. +Two bytes need to be written to read a single register, while most +other chips just require one and take the second one as the data +to be written. To prevent corrupting unknown chips, the user must +explicitely set the probe parameter. + +example: + +modprobe x1205 probe=0,0x6f + +The module supports one more option, hctosys, which is used to set the +software clock from the x1205. On systems where the x1205 is the +only hardware rtc, this parameter could be used to achieve a correct +date/time earlier in the system boot sequence. + +example: + +modprobe x1205 probe=0,0x6f hctosys=1 diff --git a/trunk/Documentation/i2c/summary b/trunk/Documentation/i2c/summary index 003c7319b8c7..aea60bf7e8f0 100644 --- a/trunk/Documentation/i2c/summary +++ b/trunk/Documentation/i2c/summary @@ -67,6 +67,7 @@ i2c-proc: The /proc/sys/dev/sensors interface for device (client) drivers Algorithm drivers ----------------- +i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT) i2c-algo-bit: A bit-banging algorithm i2c-algo-pcf: A PCF 8584 style algorithm i2c-algo-ibm_ocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT) @@ -80,5 +81,6 @@ i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatch i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit) i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT) i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit) +i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT) i2c-velleman: Velleman K8000 parallel port adapter (uses i2c-algo-bit) diff --git a/trunk/Documentation/i2c/writing-clients b/trunk/Documentation/i2c/writing-clients index 2c170032bf37..3d8d36b0ad12 100644 --- a/trunk/Documentation/i2c/writing-clients +++ b/trunk/Documentation/i2c/writing-clients @@ -571,7 +571,7 @@ SMBus communication u8 command, u8 length, u8 *values); extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, - u8 command, u8 length, u8 *values); + u8 command, u8 *values); These ones were removed in Linux 2.6.10 because they had no users, but could be added back later if needed: diff --git a/trunk/Documentation/i386/zero-page.txt b/trunk/Documentation/i386/zero-page.txt index 75b3680c41eb..c04a421f4a7c 100644 --- a/trunk/Documentation/i386/zero-page.txt +++ b/trunk/Documentation/i386/zero-page.txt @@ -37,7 +37,6 @@ Offset Type Description 0x1d0 unsigned long EFI memory descriptor map pointer 0x1d4 unsigned long EFI memory descriptor map size 0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb -0x1e4 unsigned long Scratch field for the kernel setup code 0x1e8 char number of entries in E820MAP (below) 0x1e9 unsigned char number of entries in EDDBUF (below) 0x1ea unsigned char number of entries in EDD_MBR_SIG_BUFFER (below) diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 3db68bf1d213..151f4ef978a4 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1750,8 +1750,8 @@ T: http://www.harbaum.org/till/i2c_tiny_usb S: Maintained i386 BOOT CODE -P: H. Peter Anvin -M: hpa@zytor.com +P: Riley H. Williams +M: Riley@Williams.Name L: Linux-Kernel@vger.kernel.org S: Maintained diff --git a/trunk/arch/i386/Kconfig.cpu b/trunk/arch/i386/Kconfig.cpu index 9cbe76c3aa35..5c95ceb7f122 100644 --- a/trunk/arch/i386/Kconfig.cpu +++ b/trunk/arch/i386/Kconfig.cpu @@ -344,8 +344,8 @@ config X86_CMOV depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7) default y -config X86_MINIMUM_CPU_FAMILY +config X86_MINIMUM_CPU_MODEL int - default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK - default "3" + default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP + default "0" diff --git a/trunk/arch/i386/boot/Makefile b/trunk/arch/i386/boot/Makefile index 08678a0a3d19..bfbc32098a4a 100644 --- a/trunk/arch/i386/boot/Makefile +++ b/trunk/arch/i386/boot/Makefile @@ -25,56 +25,27 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA #RAMDISK := -DRAMDISK=512 -targets := vmlinux.bin setup.bin setup.elf zImage bzImage +targets := vmlinux.bin bootsect bootsect.o \ + setup setup.o zImage bzImage subdir- := compressed -setup-y += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o -setup-y += header.o main.o mca.o memory.o pm.o pmjump.o -setup-y += printf.o string.o tty.o video.o version.o voyager.o - -# The link order of the video-*.o modules can matter. In particular, -# video-vga.o *must* be listed first, followed by video-vesa.o. -# Hardware-specific drivers should follow in the order they should be -# probed, and video-bios.o should typically be last. -setup-y += video-vga.o -setup-y += video-vesa.o -setup-y += video-bios.o - hostprogs-y := tools/build HOSTCFLAGS_build.o := $(LINUXINCLUDE) # --------------------------------------------------------------------------- -# How to compile the 16-bit code. Note we always compile for -march=i386, -# that way we can complain to the user if the CPU is insufficient. -cflags-i386 := -cflags-x86_64 := -m32 -CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ - $(cflags-$(ARCH)) \ - -Wall -Wstrict-prototypes \ - -march=i386 -mregparm=3 \ - -include $(srctree)/$(src)/code16gcc.h \ - -fno-strict-aliasing -fomit-frame-pointer \ - $(call cc-option, -ffreestanding) \ - $(call cc-option, -fno-toplevel-reorder,\ - $(call cc-option, -fno-unit-at-a-time)) \ - $(call cc-option, -fno-stack-protector) \ - $(call cc-option, -mpreferred-stack-boundary=2) -AFLAGS := $(CFLAGS) -D__ASSEMBLY__ - $(obj)/zImage: IMAGE_OFFSET := 0x1000 $(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) $(obj)/bzImage: IMAGE_OFFSET := 0x100000 -$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__ $(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ $(obj)/bzImage: BUILDFLAGS := -b quiet_cmd_image = BUILD $@ -cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \ +cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ $(obj)/vmlinux.bin $(ROOT_DEV) > $@ -$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \ +$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ $(obj)/vmlinux.bin $(obj)/tools/build FORCE $(call if_changed,image) @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' @@ -82,17 +53,12 @@ $(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) -SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) +LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary +LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext -LDFLAGS_setup.elf := -T -$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE +$(obj)/setup $(obj)/bootsect: %: %.o FORCE $(call if_changed,ld) -OBJCOPYFLAGS_setup.bin := -O binary - -$(obj)/setup.bin: $(obj)/setup.elf FORCE - $(call if_changed,objcopy) - $(obj)/compressed/vmlinux: FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ diff --git a/trunk/arch/i386/boot/a20.c b/trunk/arch/i386/boot/a20.c deleted file mode 100644 index 31348d054fca..000000000000 --- a/trunk/arch/i386/boot/a20.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/a20.c - * - * Enable A20 gate (return -1 on failure) - */ - -#include "boot.h" - -#define MAX_8042_LOOPS 100000 - -static int empty_8042(void) -{ - u8 status; - int loops = MAX_8042_LOOPS; - - while (loops--) { - io_delay(); - - status = inb(0x64); - if (status & 1) { - /* Read and discard input data */ - io_delay(); - (void)inb(0x60); - } else if (!(status & 2)) { - /* Buffers empty, finished! */ - return 0; - } - } - - return -1; -} - -/* Returns nonzero if the A20 line is enabled. The memory address - used as a test is the int $0x80 vector, which should be safe. */ - -#define A20_TEST_ADDR (4*0x80) -#define A20_TEST_SHORT 32 -#define A20_TEST_LONG 2097152 /* 2^21 */ - -static int a20_test(int loops) -{ - int ok = 0; - int saved, ctr; - - set_fs(0x0000); - set_gs(0xffff); - - saved = ctr = rdfs32(A20_TEST_ADDR); - - while (loops--) { - wrfs32(++ctr, A20_TEST_ADDR); - io_delay(); /* Serialize and make delay constant */ - ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr; - if (ok) - break; - } - - wrfs32(saved, A20_TEST_ADDR); - return ok; -} - -/* Quick test to see if A20 is already enabled */ -static int a20_test_short(void) -{ - return a20_test(A20_TEST_SHORT); -} - -/* Longer test that actually waits for A20 to come on line; this - is useful when dealing with the KBC or other slow external circuitry. */ -static int a20_test_long(void) -{ - return a20_test(A20_TEST_LONG); -} - -static void enable_a20_bios(void) -{ - asm volatile("pushfl; int $0x15; popfl" - : : "a" ((u16)0x2401)); -} - -static void enable_a20_kbc(void) -{ - empty_8042(); - - outb(0xd1, 0x64); /* Command write */ - empty_8042(); - - outb(0xdf, 0x60); /* A20 on */ - empty_8042(); -} - -static void enable_a20_fast(void) -{ - u8 port_a; - - port_a = inb(0x92); /* Configuration port A */ - port_a |= 0x02; /* Enable A20 */ - port_a &= ~0x01; /* Do not reset machine */ - outb(port_a, 0x92); -} - -/* - * Actual routine to enable A20; return 0 on ok, -1 on failure - */ - -#define A20_ENABLE_LOOPS 255 /* Number of times to try */ - -int enable_a20(void) -{ - int loops = A20_ENABLE_LOOPS; - -#if defined(CONFIG_X86_ELAN) - /* Elan croaks if we try to touch the KBC */ - enable_a20_fast(); - while (!a20_test_long()) - ; - return 0; -#elif defined(CONFIG_X86_VOYAGER) - /* On Voyager, a20_test() is unsafe? */ - enable_a20_kbc(); - return 0; -#else - while (loops--) { - /* First, check to see if A20 is already enabled - (legacy free, etc.) */ - if (a20_test_short()) - return 0; - - /* Next, try the BIOS (INT 0x15, AX=0x2401) */ - enable_a20_bios(); - if (a20_test_short()) - return 0; - - /* Try enabling A20 through the keyboard controller */ - empty_8042(); - if (a20_test_short()) - return 0; /* BIOS worked, but with delayed reaction */ - - enable_a20_kbc(); - if (a20_test_long()) - return 0; - - /* Finally, try enabling the "fast A20 gate" */ - enable_a20_fast(); - if (a20_test_long()) - return 0; - } - - return -1; -#endif -} diff --git a/trunk/arch/i386/boot/apm.c b/trunk/arch/i386/boot/apm.c deleted file mode 100644 index a34087c370c0..000000000000 --- a/trunk/arch/i386/boot/apm.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * Original APM BIOS checking by Stephen Rothwell, May 1994 - * (sfr@canb.auug.org.au) - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/apm.c - * - * Get APM BIOS information - */ - -#include "boot.h" - -#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) - -int query_apm_bios(void) -{ - u16 ax, bx, cx, dx, di; - u32 ebx, esi; - u8 err; - - /* APM BIOS installation check */ - ax = 0x5300; - bx = cx = 0; - asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" - : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) - : : "esi", "edi"); - - if (err) - return -1; /* No APM BIOS */ - - if (bx != 0x504d) /* "PM" signature */ - return -1; - - if (cx & 0x02) /* 32 bits supported? */ - return -1; - - /* Disconnect first, just in case */ - ax = 0x5304; - asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); - - /* Paranoia */ - ebx = esi = 0; - cx = dx = di = 0; - - /* 32-bit connect */ - asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" - : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), - "+S" (esi), "+D" (di), "=m" (err) - : "a" (0x5303)); - - boot_params.apm_bios_info.cseg = ax; - boot_params.apm_bios_info.offset = ebx; - boot_params.apm_bios_info.cseg_16 = cx; - boot_params.apm_bios_info.dseg = dx; - boot_params.apm_bios_info.cseg_len = (u16)esi; - boot_params.apm_bios_info.cseg_16_len = esi >> 16; - boot_params.apm_bios_info.dseg_len = di; - - if (err) - return -1; - - /* Redo the installation check as the 32-bit connect; - some BIOSes return different flags this way... */ - - ax = 0x5300; - bx = cx = 0; - asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" - : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) - : : "esi", "edi"); - - if (err || bx != 0x504d) { - /* Failure with 32-bit connect, try to disconect and ignore */ - ax = 0x5304; - bx = 0; - asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" - : "+a" (ax), "+b" (bx) - : : "ecx", "edx", "esi", "edi"); - return -1; - } - - boot_params.apm_bios_info.version = ax; - boot_params.apm_bios_info.flags = cx; - return 0; -} - -#endif diff --git a/trunk/arch/i386/boot/bitops.h b/trunk/arch/i386/boot/bitops.h deleted file mode 100644 index 8dcc8dc7db88..000000000000 --- a/trunk/arch/i386/boot/bitops.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/bitops.h - * - * Very simple bitops for the boot code. - */ - -#ifndef BOOT_BITOPS_H -#define BOOT_BITOPS_H -#define _LINUX_BITOPS_H /* Inhibit inclusion of */ - -static inline int constant_test_bit(int nr, const void *addr) -{ - const u32 *p = (const u32 *)addr; - return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0; -} -static inline int variable_test_bit(int nr, const void *addr) -{ - u8 v; - const u32 *p = (const u32 *)addr; - - asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); - return v; -} - -#define test_bit(nr,addr) \ -(__builtin_constant_p(nr) ? \ - constant_test_bit((nr),(addr)) : \ - variable_test_bit((nr),(addr))) - -static inline void set_bit(int nr, void *addr) -{ - asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); -} - -#endif /* BOOT_BITOPS_H */ diff --git a/trunk/arch/i386/boot/boot.h b/trunk/arch/i386/boot/boot.h deleted file mode 100644 index 0329c4fe4f88..000000000000 --- a/trunk/arch/i386/boot/boot.h +++ /dev/null @@ -1,296 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/boot.h - * - * Header file for the real-mode kernel code - */ - -#ifndef BOOT_BOOT_H -#define BOOT_BOOT_H - -#ifndef __ASSEMBLY__ - -#include -#include -#include -#include -#include - -/* Useful macros */ -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) - -extern struct setup_header hdr; -extern struct boot_params boot_params; - -/* Basic port I/O */ -static inline void outb(u8 v, u16 port) -{ - asm volatile("outb %0,%1" : : "a" (v), "dN" (port)); -} -static inline u8 inb(u16 port) -{ - u8 v; - asm volatile("inb %1,%0" : "=a" (v) : "dN" (port)); - return v; -} - -static inline void outw(u16 v, u16 port) -{ - asm volatile("outw %0,%1" : : "a" (v), "dN" (port)); -} -static inline u16 inw(u16 port) -{ - u16 v; - asm volatile("inw %1,%0" : "=a" (v) : "dN" (port)); - return v; -} - -static inline void outl(u32 v, u16 port) -{ - asm volatile("outl %0,%1" : : "a" (v), "dn" (port)); -} -static inline u32 inl(u32 port) -{ - u32 v; - asm volatile("inl %1,%0" : "=a" (v) : "dN" (port)); - return v; -} - -static inline void io_delay(void) -{ - const u16 DELAY_PORT = 0x80; - asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT)); -} - -/* These functions are used to reference data in other segments. */ - -static inline u16 ds(void) -{ - u16 seg; - asm("movw %%ds,%0" : "=rm" (seg)); - return seg; -} - -static inline void set_fs(u16 seg) -{ - asm volatile("movw %0,%%fs" : : "rm" (seg)); -} -static inline u16 fs(void) -{ - u16 seg; - asm("movw %%fs,%0" : "=rm" (seg)); - return seg; -} - -static inline void set_gs(u16 seg) -{ - asm volatile("movw %0,%%gs" : : "rm" (seg)); -} -static inline u16 gs(void) -{ - u16 seg; - asm("movw %%gs,%0" : "=rm" (seg)); - return seg; -} - -typedef unsigned int addr_t; - -static inline u8 rdfs8(addr_t addr) -{ - u8 v; - asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); - return v; -} -static inline u16 rdfs16(addr_t addr) -{ - u16 v; - asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); - return v; -} -static inline u32 rdfs32(addr_t addr) -{ - u32 v; - asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); - return v; -} - -static inline void wrfs8(u8 v, addr_t addr) -{ - asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v)); -} -static inline void wrfs16(u16 v, addr_t addr) -{ - asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v)); -} -static inline void wrfs32(u32 v, addr_t addr) -{ - asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v)); -} - -static inline u8 rdgs8(addr_t addr) -{ - u8 v; - asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); - return v; -} -static inline u16 rdgs16(addr_t addr) -{ - u16 v; - asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); - return v; -} -static inline u32 rdgs32(addr_t addr) -{ - u32 v; - asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); - return v; -} - -static inline void wrgs8(u8 v, addr_t addr) -{ - asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v)); -} -static inline void wrgs16(u16 v, addr_t addr) -{ - asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v)); -} -static inline void wrgs32(u32 v, addr_t addr) -{ - asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v)); -} - -/* Note: these only return true/false, not a signed return value! */ -static inline int memcmp(const void *s1, const void *s2, size_t len) -{ - u8 diff; - asm("repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); - return diff; -} - -static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) -{ - u8 diff; - asm("fs; repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); - return diff; -} -static inline int memcmp_gs(const void *s1, addr_t s2, size_t len) -{ - u8 diff; - asm("gs; repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); - return diff; -} - -static inline int isdigit(int ch) -{ - return (ch >= '0') && (ch <= '9'); -} - -/* Heap -- available for dynamic lists. */ -#define STACK_SIZE 512 /* Minimum number of bytes for stack */ - -extern char _end[]; -extern char *HEAP; -extern char *heap_end; -#define RESET_HEAP() ((void *)( HEAP = _end )) -static inline char *__get_heap(size_t s, size_t a, size_t n) -{ - char *tmp; - - HEAP = (char *)(((size_t)HEAP+(a-1)) & ~(a-1)); - tmp = HEAP; - HEAP += s*n; - return tmp; -} -#define GET_HEAP(type, n) \ - ((type *)__get_heap(sizeof(type),__alignof__(type),(n))) - -static inline int heap_free(void) -{ - return heap_end-HEAP; -} - -/* copy.S */ - -void copy_to_fs(addr_t dst, void *src, size_t len); -void *copy_from_fs(void *dst, addr_t src, size_t len); -void copy_to_gs(addr_t dst, void *src, size_t len); -void *copy_from_gs(void *dst, addr_t src, size_t len); -void *memcpy(void *dst, void *src, size_t len); -void *memset(void *dst, int c, size_t len); - -#define memcpy(d,s,l) __builtin_memcpy(d,s,l) -#define memset(d,c,l) __builtin_memset(d,c,l) - -/* a20.c */ -int enable_a20(void); - -/* apm.c */ -int query_apm_bios(void); - -/* cmdline.c */ -int cmdline_find_option(const char *option, char *buffer, int bufsize); - -/* cpu.c, cpucheck.c */ -int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); -int validate_cpu(void); - -/* edd.c */ -void query_edd(void); - -/* header.S */ -void __attribute__((noreturn)) die(void); - -/* mca.c */ -int query_mca(void); - -/* memory.c */ -int detect_memory(void); - -/* pm.c */ -void __attribute__((noreturn)) go_to_protected_mode(void); - -/* pmjump.S */ -void __attribute__((noreturn)) - protected_mode_jump(u32 entrypoint, u32 bootparams); - -/* printf.c */ -int sprintf(char *buf, const char *fmt, ...); -int vsprintf(char *buf, const char *fmt, va_list args); -int printf(const char *fmt, ...); - -/* string.c */ -int strcmp(const char *str1, const char *str2); -size_t strnlen(const char *s, size_t maxlen); -unsigned int atou(const char *s); - -/* tty.c */ -void puts(const char *); -void putchar(int); -int getchar(void); -void kbd_flush(void); -int getchar_timeout(void); - -/* video.c */ -void set_video(void); - -/* video-vesa.c */ -void vesa_store_edid(void); - -/* voyager.c */ -int query_voyager(void); - -#endif /* __ASSEMBLY__ */ - -#endif /* BOOT_BOOT_H */ diff --git a/trunk/arch/i386/boot/bootsect.S b/trunk/arch/i386/boot/bootsect.S new file mode 100644 index 000000000000..011b7a4993d4 --- /dev/null +++ b/trunk/arch/i386/boot/bootsect.S @@ -0,0 +1,98 @@ +/* + * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds + * + * modified by Drew Eckhardt + * modified by Bruce Evans (bde) + * modified by Chris Noe (May 1999) (as86 -> gas) + * gutted by H. Peter Anvin (Jan 2003) + * + * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment + * addresses must be multiplied by 16 to obtain their respective linear + * addresses. To avoid confusion, linear addresses are written using leading + * hex while segment addresses are written as segment:offset. + * + */ + +#include + +SETUPSECTS = 4 /* default nr of setup-sectors */ +BOOTSEG = 0x07C0 /* original address of boot-sector */ +INITSEG = DEF_INITSEG /* we move boot here - out of the way */ +SETUPSEG = DEF_SETUPSEG /* setup starts here */ +SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ +SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ + /* to be loaded */ +ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ +SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ + +#ifndef SVGA_MODE +#define SVGA_MODE ASK_VGA +#endif + +#ifndef RAMDISK +#define RAMDISK 0 +#endif + +#ifndef ROOT_RDONLY +#define ROOT_RDONLY 1 +#endif + +.code16 +.text + +.global _start +_start: + + # Normalize the start address + jmpl $BOOTSEG, $start2 + +start2: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw $0x7c00, %sp + sti + cld + + movw $bugger_off_msg, %si + +msg_loop: + lodsb + andb %al, %al + jz die + movb $0xe, %ah + movw $7, %bx + int $0x10 + jmp msg_loop + +die: + # Allow the user to press a key, then reboot + xorw %ax, %ax + int $0x16 + int $0x19 + + # int 0x19 should never return. In case it does anyway, + # invoke the BIOS reset code... + ljmp $0xf000,$0xfff0 + + +bugger_off_msg: + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" + .ascii "\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" + .byte 0 + + + # Kernel attributes; used by setup + + .org 497 +setup_sects: .byte SETUPSECTS +root_flags: .word ROOT_RDONLY +syssize: .word SYSSIZE +swap_dev: .word SWAP_DEV +ram_size: .word RAMDISK +vid_mode: .word SVGA_MODE +root_dev: .word ROOT_DEV +boot_flag: .word 0xAA55 diff --git a/trunk/arch/i386/boot/cmdline.c b/trunk/arch/i386/boot/cmdline.c deleted file mode 100644 index 34bb778c4357..000000000000 --- a/trunk/arch/i386/boot/cmdline.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/cmdline.c - * - * Simple command-line parser for early boot. - */ - -#include "boot.h" - -static inline int myisspace(u8 c) -{ - return c <= ' '; /* Close enough approximation */ -} - -/* - * Find a non-boolean option, that is, "option=argument". In accordance - * with standard Linux practice, if this option is repeated, this returns - * the last instance on the command line. - * - * Returns the length of the argument (regardless of if it was - * truncated to fit in the buffer), or -1 on not found. - */ -int cmdline_find_option(const char *option, char *buffer, int bufsize) -{ - u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr; - addr_t cptr; - char c; - int len = -1; - const char *opptr = NULL; - char *bufptr = buffer; - enum { - st_wordstart, /* Start of word/after whitespace */ - st_wordcmp, /* Comparing this word */ - st_wordskip, /* Miscompare, skip */ - st_bufcpy /* Copying this to buffer */ - } state = st_wordstart; - - if (!cmdline_ptr || cmdline_ptr >= 0x100000) - return -1; /* No command line, or inaccessible */ - - cptr = cmdline_ptr & 0xf; - set_fs(cmdline_ptr >> 4); - - while (cptr < 0x10000 && (c = rdfs8(cptr++))) { - switch (state) { - case st_wordstart: - if (myisspace(c)) - break; - - /* else */ - state = st_wordcmp; - opptr = option; - /* fall through */ - - case st_wordcmp: - if (c == '=' && !*opptr) { - len = 0; - bufptr = buffer; - state = st_bufcpy; - } else if (myisspace(c)) { - state = st_wordstart; - } else if (c != *opptr++) { - state = st_wordskip; - } - break; - - case st_wordskip: - if (myisspace(c)) - state = st_wordstart; - break; - - case st_bufcpy: - if (myisspace(c)) { - state = st_wordstart; - } else { - if (len < bufsize-1) - *bufptr++ = c; - len++; - } - break; - } - } - - if (bufsize) - *bufptr = '\0'; - - return len; -} diff --git a/trunk/arch/i386/boot/code16gcc.h b/trunk/arch/i386/boot/code16gcc.h deleted file mode 100644 index 3bd848093b9d..000000000000 --- a/trunk/arch/i386/boot/code16gcc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * code16gcc.h - * - * This file is -include'd when compiling 16-bit C code. - * Note: this asm() needs to be emitted before gcc omits any code. - * Depending on gcc version, this requires -fno-unit-at-a-time or - * -fno-toplevel-reorder. - * - * Hopefully gcc will eventually have a real -m16 option so we can - * drop this hack long term. - */ - -#ifndef __ASSEMBLY__ -asm(".code16gcc"); -#endif diff --git a/trunk/arch/i386/boot/compressed/Makefile b/trunk/arch/i386/boot/compressed/Makefile index 189fa1dbefcc..a661217f33ec 100644 --- a/trunk/arch/i386/boot/compressed/Makefile +++ b/trunk/arch/i386/boot/compressed/Makefile @@ -9,14 +9,9 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \ EXTRA_AFLAGS := -traditional LDFLAGS_vmlinux := -T +CFLAGS_misc.o += -fPIC hostprogs-y := relocs -CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ - -fno-strict-aliasing -fPIC \ - $(call cc-option,-ffreestanding) \ - $(call cc-option,-fno-stack-protector) -LDFLAGS := -m elf_i386 - $(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE $(call if_changed,ld) @: diff --git a/trunk/arch/i386/boot/compressed/head.S b/trunk/arch/i386/boot/compressed/head.S index f35ea2237522..3517a32aaf41 100644 --- a/trunk/arch/i386/boot/compressed/head.S +++ b/trunk/arch/i386/boot/compressed/head.S @@ -45,10 +45,10 @@ startup_32: * at and where we were actually loaded at. This can only be done * with a short local call on x86. Nothing else will tell us what * address we are running at. The reserved chunk of the real-mode - * data at 0x1e4 (defined as a scratch field) are used as the stack - * for this calculation. Only 4 bytes are needed. + * data at 0x34-0x3f are used as the stack for this calculation. + * Only 4 bytes are needed. */ - leal (0x1e4+4)(%esi), %esp + leal 0x40(%esi), %esp call 1f 1: popl %ebp subl $1b, %ebp diff --git a/trunk/arch/i386/boot/copy.S b/trunk/arch/i386/boot/copy.S deleted file mode 100644 index ef127e56a3cf..000000000000 --- a/trunk/arch/i386/boot/copy.S +++ /dev/null @@ -1,101 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/copy.S - * - * Memory copy routines - */ - - .code16gcc - .text - - .globl memcpy - .type memcpy, @function -memcpy: - pushw %si - pushw %di - movw %ax, %di - movw %dx, %si - pushw %cx - shrw $2, %cx - rep; movsl - popw %cx - andw $3, %cx - rep; movsb - popw %di - popw %si - ret - .size memcpy, .-memcpy - - .globl memset - .type memset, @function -memset: - pushw %di - movw %ax, %di - movzbl %dl, %eax - imull $0x01010101,%eax - pushw %cx - shrw $2, %cx - rep; stosl - popw %cx - andw $3, %cx - rep; stosb - popw %di - ret - .size memset, .-memset - - .globl copy_from_fs - .type copy_from_fs, @function -copy_from_fs: - pushw %ds - pushw %fs - popw %ds - call memcpy - popw %ds - ret - .size copy_from_fs, .-copy_from_fs - - .globl copy_to_fs - .type copy_to_fs, @function -copy_to_fs: - pushw %es - pushw %fs - popw %es - call memcpy - popw %es - ret - .size copy_to_fs, .-copy_to_fs - -#if 0 /* Not currently used, but can be enabled as needed */ - - .globl copy_from_gs - .type copy_from_gs, @function -copy_from_gs: - pushw %ds - pushw %gs - popw %ds - call memcpy - popw %ds - ret - .size copy_from_gs, .-copy_from_gs - .globl copy_to_gs - - .type copy_to_gs, @function -copy_to_gs: - pushw %es - pushw %gs - popw %es - call memcpy - popw %es - ret - .size copy_to_gs, .-copy_to_gs - -#endif diff --git a/trunk/arch/i386/boot/cpu.c b/trunk/arch/i386/boot/cpu.c deleted file mode 100644 index 2a5c32da5852..000000000000 --- a/trunk/arch/i386/boot/cpu.c +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/cpu.c - * - * Check for obligatory CPU features and abort if the features are not - * present. - */ - -#include "boot.h" -#include "bitops.h" -#include - -static char *cpu_name(int level) -{ - static char buf[6]; - - if (level == 64) { - return "x86-64"; - } else { - sprintf(buf, "i%d86", level); - return buf; - } -} - -int validate_cpu(void) -{ - u32 *err_flags; - int cpu_level, req_level; - - check_cpu(&cpu_level, &req_level, &err_flags); - - if (cpu_level < req_level) { - printf("This kernel requires an %s CPU, ", - cpu_name(req_level)); - printf("but only detected an %s CPU.\n", - cpu_name(cpu_level)); - return -1; - } - - if (err_flags) { - int i, j; - puts("This kernel requires the following features " - "not present on the CPU:\n"); - - for (i = 0; i < NCAPINTS; i++) { - u32 e = err_flags[i]; - - for (j = 0; j < 32; j++) { - if (e & 1) - printf("%d:%d ", i, j); - - e >>= 1; - } - } - putchar('\n'); - return -1; - } else { - return 0; - } -} diff --git a/trunk/arch/i386/boot/cpucheck.c b/trunk/arch/i386/boot/cpucheck.c deleted file mode 100644 index 8b0f4473b083..000000000000 --- a/trunk/arch/i386/boot/cpucheck.c +++ /dev/null @@ -1,267 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/cpucheck.c - * - * Check for obligatory CPU features and abort if the features are not - * present. This code should be compilable as 16-, 32- or 64-bit - * code, so be very careful with types and inline assembly. - * - * This code should not contain any messages; that requires an - * additional wrapper. - * - * As written, this code is not safe for inclusion into the kernel - * proper (after FPU initialization, in particular). - */ - -#ifdef _SETUP -# include "boot.h" -# include "bitops.h" -#endif -#include -#include -#include -#include -#include - -struct cpu_features { - int level; /* Family, or 64 for x86-64 */ - int model; - u32 flags[NCAPINTS]; -}; - -static struct cpu_features cpu; -static u32 cpu_vendor[3]; -static u32 err_flags[NCAPINTS]; - -#ifdef CONFIG_X86_64 -static const int req_level = 64; -#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY) -static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY; -#else -static const int req_level = 3; -#endif - -static const u32 req_flags[NCAPINTS] = -{ - REQUIRED_MASK0, - REQUIRED_MASK1, - REQUIRED_MASK2, - REQUIRED_MASK3, - REQUIRED_MASK4, - REQUIRED_MASK5, - REQUIRED_MASK6, - REQUIRED_MASK7, -}; - -#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) - -static int is_amd(void) -{ - return cpu_vendor[0] == A32('A','u','t','h') && - cpu_vendor[1] == A32('e','n','t','i') && - cpu_vendor[2] == A32('c','A','M','D'); -} - -static int is_centaur(void) -{ - return cpu_vendor[0] == A32('C','e','n','t') && - cpu_vendor[1] == A32('a','u','r','H') && - cpu_vendor[2] == A32('a','u','l','s'); -} - -static int is_transmeta(void) -{ - return cpu_vendor[0] == A32('G','e','n','u') && - cpu_vendor[1] == A32('i','n','e','T') && - cpu_vendor[2] == A32('M','x','8','6'); -} - -static int has_fpu(void) -{ - u16 fcw = -1, fsw = -1; - u32 cr0; - - asm("movl %%cr0,%0" : "=r" (cr0)); - if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { - cr0 &= ~(X86_CR0_EM|X86_CR0_TS); - asm volatile("movl %0,%%cr0" : : "r" (cr0)); - } - - asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw)); - - return fsw == 0 && (fcw & 0x103f) == 0x003f; -} - -static int has_eflag(u32 mask) -{ - u32 f0, f1; - - asm("pushfl ; " - "pushfl ; " - "popl %0 ; " - "movl %0,%1 ; " - "xorl %2,%1 ; " - "pushl %1 ; " - "popfl ; " - "pushfl ; " - "popl %1 ; " - "popfl" - : "=r" (f0), "=r" (f1) - : "g" (mask)); - - return !!((f0^f1) & mask); -} - -static void get_flags(void) -{ - u32 max_intel_level, max_amd_level; - u32 tfms; - - if (has_fpu()) - set_bit(X86_FEATURE_FPU, cpu.flags); - - if (has_eflag(X86_EFLAGS_ID)) { - asm("cpuid" - : "=a" (max_intel_level), - "=b" (cpu_vendor[0]), - "=d" (cpu_vendor[1]), - "=c" (cpu_vendor[2]) - : "a" (0)); - - if (max_intel_level >= 0x00000001 && - max_intel_level <= 0x0000ffff) { - asm("cpuid" - : "=a" (tfms), - "=c" (cpu.flags[4]), - "=d" (cpu.flags[0]) - : "a" (0x00000001) - : "ebx"); - cpu.level = (tfms >> 8) & 15; - cpu.model = (tfms >> 4) & 15; - if (cpu.level >= 6) - cpu.model += ((tfms >> 16) & 0xf) << 4; - } - - asm("cpuid" - : "=a" (max_amd_level) - : "a" (0x80000000) - : "ebx", "ecx", "edx"); - - if (max_amd_level >= 0x80000001 && - max_amd_level <= 0x8000ffff) { - u32 eax = 0x80000001; - asm("cpuid" - : "+a" (eax), - "=c" (cpu.flags[6]), - "=d" (cpu.flags[1]) - : : "ebx"); - } - } -} - -/* Returns a bitmask of which words we have error bits in */ -static int check_flags(void) -{ - u32 err; - int i; - - err = 0; - for (i = 0; i < NCAPINTS; i++) { - err_flags[i] = req_flags[i] & ~cpu.flags[i]; - if (err_flags[i]) - err |= 1 << i; - } - - return err; -} - -/* - * Returns -1 on error. - * - * *cpu_level is set to the current CPU level; *req_level to the required - * level. x86-64 is considered level 64 for this purpose. - * - * *err_flags_ptr is set to the flags error array if there are flags missing. - */ -int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) -{ - int err; - - memset(&cpu.flags, 0, sizeof cpu.flags); - cpu.level = 3; - - if (has_eflag(X86_EFLAGS_AC)) - cpu.level = 4; - - get_flags(); - err = check_flags(); - - if (test_bit(X86_FEATURE_LM, cpu.flags)) - cpu.level = 64; - - if (err == 0x01 && - !(err_flags[0] & - ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) && - is_amd()) { - /* If this is an AMD and we're only missing SSE+SSE2, try to - turn them on */ - - u32 ecx = MSR_K7_HWCR; - u32 eax, edx; - - asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); - eax &= ~(1 << 15); - asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); - - get_flags(); /* Make sure it really did something */ - err = check_flags(); - } else if (err == 0x01 && - !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) && - is_centaur() && cpu.model >= 6) { - /* If this is a VIA C3, we might have to enable CX8 - explicitly */ - - u32 ecx = MSR_VIA_FCR; - u32 eax, edx; - - asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); - eax |= (1<<1)|(1<<7); - asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); - - set_bit(X86_FEATURE_CX8, cpu.flags); - err = check_flags(); - } else if (err == 0x01 && is_transmeta()) { - /* Transmeta might have masked feature bits in word 0 */ - - u32 ecx = 0x80860004; - u32 eax, edx; - u32 level = 1; - - asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); - asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); - asm("cpuid" - : "+a" (level), "=d" (cpu.flags[0]) - : : "ecx", "ebx"); - asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); - - err = check_flags(); - } - - if (err_flags_ptr) - *err_flags_ptr = err ? err_flags : NULL; - if (cpu_level_ptr) - *cpu_level_ptr = cpu.level; - if (req_level_ptr) - *req_level_ptr = req_level; - - return (cpu.level < req_level || err) ? -1 : 0; -} diff --git a/trunk/arch/i386/boot/edd.S b/trunk/arch/i386/boot/edd.S new file mode 100644 index 000000000000..34321368011a --- /dev/null +++ b/trunk/arch/i386/boot/edd.S @@ -0,0 +1,231 @@ +/* + * BIOS Enhanced Disk Drive support + * Copyright (C) 2002, 2003, 2004 Dell, Inc. + * by Matt Domsch October 2002 + * conformant to T13 Committee www.t13.org + * projects 1572D, 1484D, 1386D, 1226DT + * disk signature read by Matt Domsch + * and Andrew Wilks September 2003, June 2004 + * legacy CHS retrieval by Patrick J. LoPresti + * March 2004 + * Command line option parsing, Matt Domsch, November 2004 + */ + +#include +#include + +#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) + +# It is assumed that %ds == INITSEG here + + movb $0, (EDD_MBR_SIG_NR_BUF) + movb $0, (EDDNR) + +# Check the command line for options: +# edd=of disables EDD completely (edd=off) +# edd=sk skips the MBR test (edd=skipmbr) +# edd=on re-enables EDD (edd=on) + + pushl %esi + movw $edd_mbr_sig_start, %di # Default to edd=on + + movl %cs:(cmd_line_ptr), %esi + andl %esi, %esi + jz old_cl # Old boot protocol? + +# Convert to a real-mode pointer in fs:si + movl %esi, %eax + shrl $4, %eax + movw %ax, %fs + andw $0xf, %si + jmp have_cl_pointer + +# Old-style boot protocol? +old_cl: + push %ds # aka INITSEG + pop %fs + + cmpw $0xa33f, (0x20) + jne done_cl # No command line at all? + movw (0x22), %si # Pointer relative to INITSEG + +# fs:si has the pointer to the command line now +have_cl_pointer: + +# Loop through kernel command line one byte at a time. Just in +# case the loader is buggy and failed to null-terminate the command line +# terminate if we get close enough to the end of the segment that we +# cannot fit "edd=XX"... +cl_atspace: + cmpw $-5, %si # Watch for segment wraparound + jae done_cl + movl %fs:(%si), %eax + andb %al, %al # End of line? + jz done_cl + cmpl $EDD_CL_EQUALS, %eax + jz found_edd_equals + cmpb $0x20, %al # <= space consider whitespace + ja cl_skipword + incw %si + jmp cl_atspace + +cl_skipword: + cmpw $-5, %si # Watch for segment wraparound + jae done_cl + movb %fs:(%si), %al # End of string? + andb %al, %al + jz done_cl + cmpb $0x20, %al + jbe cl_atspace + incw %si + jmp cl_skipword + +found_edd_equals: +# only looking at first two characters after equals +# late overrides early on the command line, so keep going after finding something + movw %fs:4(%si), %ax + cmpw $EDD_CL_OFF, %ax # edd=of + je do_edd_off + cmpw $EDD_CL_SKIP, %ax # edd=sk + je do_edd_skipmbr + cmpw $EDD_CL_ON, %ax # edd=on + je do_edd_on + jmp cl_skipword +do_edd_skipmbr: + movw $edd_start, %di + jmp cl_skipword +do_edd_off: + movw $edd_done, %di + jmp cl_skipword +do_edd_on: + movw $edd_mbr_sig_start, %di + jmp cl_skipword + +done_cl: + popl %esi + jmpw *%di + +# Read the first sector of each BIOS disk device and store the 4-byte signature +edd_mbr_sig_start: + movb $0x80, %dl # from device 80 + movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx +edd_mbr_sig_read: + movl $0xFFFFFFFF, %eax + movl %eax, (%bx) # assume failure + pushw %bx + movb $READ_SECTORS, %ah + movb $1, %al # read 1 sector + movb $0, %dh # at head 0 + movw $1, %cx # cylinder 0, sector 0 + pushw %es + pushw %ds + popw %es + movw $EDDBUF, %bx # disk's data goes into EDDBUF + pushw %dx # work around buggy BIOSes + stc # work around buggy BIOSes + int $0x13 + sti # work around buggy BIOSes + popw %dx + popw %es + popw %bx + jc edd_mbr_sig_done # on failure, we're done. + cmpb $0, %ah # some BIOSes do not set CF + jne edd_mbr_sig_done # on failure, we're done. + movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR + movl %eax, (%bx) # store success + incb (EDD_MBR_SIG_NR_BUF) # note that we stored something + incb %dl # increment to next device + addw $4, %bx # increment sig buffer ptr + cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space? + jb edd_mbr_sig_read # keep looping +edd_mbr_sig_done: + +# Do the BIOS Enhanced Disk Drive calls +# This consists of two calls: +# int 13h ah=41h "Check Extensions Present" +# int 13h ah=48h "Get Device Parameters" +# int 13h ah=08h "Legacy Get Device Parameters" +# +# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use +# in the boot_params at EDDBUF. The first four bytes of which are +# used to store the device number, interface support map and version +# results from fn41. The next four bytes are used to store the legacy +# cylinders, heads, and sectors from fn08. The following 74 bytes are used to +# store the results from fn48. Starting from device 80h, fn41, then fn48 +# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE). +# Then the pointer is incremented to store the data for the next call. +# This repeats until either a device doesn't exist, or until EDDMAXNR +# devices have been stored. +# The one tricky part is that ds:si always points EDDEXTSIZE bytes into +# the structure, and the fn41 and fn08 results are stored at offsets +# from there. This removes the need to increment the pointer for +# every store, and leaves it ready for the fn48 call. +# A second one-byte buffer, EDDNR, in the boot_params stores +# the number of BIOS devices which exist, up to EDDMAXNR. +# In setup.c, copy_edd() stores both boot_params buffers away +# for later use, as they would get overwritten otherwise. +# This code is sensitive to the size of the structs in edd.h +edd_start: + # %ds points to the bootsector + # result buffer for fn48 + movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results + # kept just before that + movb $0x80, %dl # BIOS device 0x80 + +edd_check_ext: + movb $CHECKEXTENSIONSPRESENT, %ah # Function 41 + movw $EDDMAGIC1, %bx # magic + int $0x13 # make the call + jc edd_done # no more BIOS devices + + cmpw $EDDMAGIC2, %bx # is magic right? + jne edd_next # nope, next... + + movb %dl, %ds:-8(%si) # store device number + movb %ah, %ds:-7(%si) # store version + movw %cx, %ds:-6(%si) # store extensions + incb (EDDNR) # note that we stored something + +edd_get_device_params: + movw $EDDPARMSIZE, %ds:(%si) # put size + movw $0x0, %ds:2(%si) # work around buggy BIOSes + movb $GETDEVICEPARAMETERS, %ah # Function 48 + int $0x13 # make the call + # Don't check for fail return + # it doesn't matter. +edd_get_legacy_chs: + xorw %ax, %ax + movw %ax, %ds:-4(%si) + movw %ax, %ds:-2(%si) + # Ralf Brown's Interrupt List says to set ES:DI to + # 0000h:0000h "to guard against BIOS bugs" + pushw %es + movw %ax, %es + movw %ax, %di + pushw %dx # legacy call clobbers %dl + movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08 + int $0x13 # make the call + jc edd_legacy_done # failed + movb %cl, %al # Low 6 bits are max + andb $0x3F, %al # sector number + movb %al, %ds:-1(%si) # Record max sect + movb %dh, %ds:-2(%si) # Record max head number + movb %ch, %al # Low 8 bits of max cyl + shr $6, %cl + movb %cl, %ah # High 2 bits of max cyl + movw %ax, %ds:-4(%si) + +edd_legacy_done: + popw %dx + popw %es + movw %si, %ax # increment si + addw $EDDPARMSIZE+EDDEXTSIZE, %ax + movw %ax, %si + +edd_next: + incb %dl # increment to next device + cmpb $EDDMAXNR, (EDDNR) # Out of space? + jb edd_check_ext # keep looping + +edd_done: +#endif diff --git a/trunk/arch/i386/boot/edd.c b/trunk/arch/i386/boot/edd.c deleted file mode 100644 index 25a282494f4c..000000000000 --- a/trunk/arch/i386/boot/edd.c +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/edd.c - * - * Get EDD BIOS disk information - */ - -#include "boot.h" -#include - -#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) - -struct edd_dapa { - u8 pkt_size; - u8 rsvd; - u16 sector_cnt; - u16 buf_off, buf_seg; - u64 lba; - u64 buf_lin_addr; -}; - -/* - * Read the MBR (first sector) from a specific device. - */ -static int read_mbr(u8 devno, void *buf) -{ - struct edd_dapa dapa; - u16 ax, bx, cx, dx, si; - - memset(&dapa, 0, sizeof dapa); - dapa.pkt_size = sizeof(dapa); - dapa.sector_cnt = 1; - dapa.buf_off = (size_t)buf; - dapa.buf_seg = ds(); - /* dapa.lba = 0; */ - - ax = 0x4200; /* Extended Read */ - si = (size_t)&dapa; - dx = devno; - asm("pushfl; stc; int $0x13; setc %%al; popfl" - : "+a" (ax), "+S" (si), "+d" (dx) - : "m" (dapa) - : "ebx", "ecx", "edi", "memory"); - - if (!(u8)ax) - return 0; /* OK */ - - ax = 0x0201; /* Legacy Read, one sector */ - cx = 0x0001; /* Sector 0-0-1 */ - dx = devno; - bx = (size_t)buf; - asm("pushfl; stc; int $0x13; setc %%al; popfl" - : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) - : : "esi", "edi", "memory"); - - return -(u8)ax; /* 0 or -1 */ -} - -static u32 read_mbr_sig(u8 devno, struct edd_info *ei) -{ - int sector_size; - char *mbrbuf_ptr, *mbrbuf_end; - u32 mbrsig; - u32 buf_base, mbr_base; - extern char _end[]; - static char mbr_buf[1024]; - - sector_size = ei->params.bytes_per_sector; - if (!sector_size) - sector_size = 512; /* Best available guess */ - - buf_base = (ds() << 4) + (u32)&_end; - mbr_base = (buf_base+sector_size-1) & ~(sector_size-1); - mbrbuf_ptr = mbr_buf + (mbr_base-buf_base); - mbrbuf_end = mbrbuf_ptr + sector_size; - - if (!(boot_params.hdr.loadflags & CAN_USE_HEAP)) - return 0; - if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr) - return 0; - - if (read_mbr(devno, mbrbuf_ptr)) - return 0; - - mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET]; - return mbrsig; -} - -static int get_edd_info(u8 devno, struct edd_info *ei) -{ - u16 ax, bx, cx, dx, di; - - memset(ei, 0, sizeof *ei); - - /* Check Extensions Present */ - - ax = 0x4100; - bx = EDDMAGIC1; - dx = devno; - asm("pushfl; stc; int $0x13; setc %%al; popfl" - : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx) - : : "esi", "edi"); - - if ((u8)ax) - return -1; /* No extended information */ - - if (bx != EDDMAGIC2) - return -1; - - ei->device = devno; - ei->version = ax >> 8; /* EDD version number */ - ei->interface_support = cx; /* EDD functionality subsets */ - - /* Extended Get Device Parameters */ - - ei->params.length = sizeof(ei->params); - ax = 0x4800; - dx = devno; - asm("pushfl; int $0x13; popfl" - : "+a" (ax), "+d" (dx) - : "S" (&ei->params) - : "ebx", "ecx", "edi"); - - /* Get legacy CHS parameters */ - - /* Ralf Brown recommends setting ES:DI to 0:0 */ - ax = 0x0800; - dx = devno; - di = 0; - asm("pushw %%es; " - "movw %%di,%%es; " - "pushfl; stc; int $0x13; setc %%al; popfl; " - "popw %%es" - : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di) - : : "esi"); - - if ((u8)ax == 0) { - ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2); - ei->legacy_max_head = dx >> 8; - ei->legacy_sectors_per_track = cx & 0x3f; - } - - return 0; -} - -void query_edd(void) -{ - char eddarg[8]; - int do_mbr = 1; - int do_edd = 1; - int devno; - struct edd_info ei, *edp; - - if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) { - if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) - do_mbr = 0; - else if (!strcmp(eddarg, "off")) - do_edd = 0; - } - - edp = (struct edd_info *)boot_params.eddbuf; - - if (!do_edd) - return; - - for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) { - /* - * Scan the BIOS-supported hard disks and query EDD - * information... - */ - get_edd_info(devno, &ei); - - if (boot_params.eddbuf_entries < EDDMAXNR) { - memcpy(edp, &ei, sizeof ei); - edp++; - boot_params.eddbuf_entries++; - } - - if (do_mbr) { - u32 mbr_sig; - mbr_sig = read_mbr_sig(devno, &ei); - boot_params.edd_mbr_sig_buffer[devno-0x80] = mbr_sig; - } - } -} - -#endif diff --git a/trunk/arch/i386/boot/header.S b/trunk/arch/i386/boot/header.S deleted file mode 100644 index 6b9923fb6eae..000000000000 --- a/trunk/arch/i386/boot/header.S +++ /dev/null @@ -1,283 +0,0 @@ -/* - * header.S - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * Based on bootsect.S and setup.S - * modified by more people than can be counted - * - * Rewritten as a common file by H. Peter Anvin (Apr 2007) - * - * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment - * addresses must be multiplied by 16 to obtain their respective linear - * addresses. To avoid confusion, linear addresses are written using leading - * hex while segment addresses are written as segment:offset. - * - */ - -#include -#include -#include -#include -#include -#include -#include "boot.h" - -SETUPSECTS = 4 /* default nr of setup-sectors */ -BOOTSEG = 0x07C0 /* original address of boot-sector */ -SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ -SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ - /* to be loaded */ -ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ -SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ - -#ifndef SVGA_MODE -#define SVGA_MODE ASK_VGA -#endif - -#ifndef RAMDISK -#define RAMDISK 0 -#endif - -#ifndef ROOT_RDONLY -#define ROOT_RDONLY 1 -#endif - - .code16 - .section ".bstext", "ax" - - .global bootsect_start -bootsect_start: - - # Normalize the start address - ljmp $BOOTSEG, $start2 - -start2: - movw %cs, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - xorw %sp, %sp - sti - cld - - movw $bugger_off_msg, %si - -msg_loop: - lodsb - andb %al, %al - jz bs_die - movb $0xe, %ah - movw $7, %bx - int $0x10 - jmp msg_loop - -bs_die: - # Allow the user to press a key, then reboot - xorw %ax, %ax - int $0x16 - int $0x19 - - # int 0x19 should never return. In case it does anyway, - # invoke the BIOS reset code... - ljmp $0xf000,$0xfff0 - - .section ".bsdata", "a" -bugger_off_msg: - .ascii "Direct booting from floppy is no longer supported.\r\n" - .ascii "Please use a boot loader program instead.\r\n" - .ascii "\n" - .ascii "Remove disk and press any key to reboot . . .\r\n" - .byte 0 - - - # Kernel attributes; used by setup. This is part 1 of the - # header, from the old boot sector. - - .section ".header", "a" - .globl hdr -hdr: -setup_sects: .byte SETUPSECTS -root_flags: .word ROOT_RDONLY -syssize: .long SYSSIZE -ram_size: .word RAMDISK -vid_mode: .word SVGA_MODE -root_dev: .word ROOT_DEV -boot_flag: .word 0xAA55 - - # offset 512, entry point - - .globl _start -_start: - # Explicitly enter this as bytes, or the assembler - # tries to generate a 3-byte jump here, which causes - # everything else to push off to the wrong offset. - .byte 0xeb # short (2-byte) jump - .byte start_of_setup-1f -1: - - # Part 2 of the header, from the old setup.S - - .ascii "HdrS" # header signature - .word 0x0206 # header version number (>= 0x0105) - # or else old loadlin-1.5 will fail) - .globl realmode_swtch -realmode_swtch: .word 0, 0 # default_switch, SETUPSEG -start_sys_seg: .word SYSSEG - .word kernel_version-512 # pointing to kernel version string - # above section of header is compatible - # with loadlin-1.5 (header v1.5). Don't - # change it. - -type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, - # Bootlin, SYSLX, bootsect...) - # See Documentation/i386/boot.txt for - # assigned ids - -# flags, unused bits must be zero (RFU) bit within loadflags -loadflags: -LOADED_HIGH = 1 # If set, the kernel is loaded high -CAN_USE_HEAP = 0x80 # If set, the loader also has set - # heap_end_ptr to tell how much - # space behind setup.S can be used for - # heap purposes. - # Only the loader knows what is free -#ifndef __BIG_KERNEL__ - .byte 0 -#else - .byte LOADED_HIGH -#endif - -setup_move_size: .word 0x8000 # size to move, when setup is not - # loaded at 0x90000. We will move setup - # to 0x90000 then just before jumping - # into the kernel. However, only the - # loader knows how much data behind - # us also needs to be loaded. - -code32_start: # here loaders can put a different - # start address for 32-bit code. -#ifndef __BIG_KERNEL__ - .long 0x1000 # 0x1000 = default for zImage -#else - .long 0x100000 # 0x100000 = default for big kernel -#endif - -ramdisk_image: .long 0 # address of loaded ramdisk image - # Here the loader puts the 32-bit - # address where it loaded the image. - # This only will be read by the kernel. - -ramdisk_size: .long 0 # its size in bytes - -bootsect_kludge: - .long 0 # obsolete - -heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later) - # space from here (exclusive) down to - # end of setup code can be used by setup - # for local heap purposes. - -pad1: .word 0 -cmd_line_ptr: .long 0 # (Header version 0x0202 or later) - # If nonzero, a 32-bit pointer - # to the kernel command line. - # The command line should be - # located between the start of - # setup and the end of low - # memory (0xa0000), or it may - # get overwritten before it - # gets read. If this field is - # used, there is no longer - # anything magical about the - # 0x90000 segment; the setup - # can be located anywhere in - # low memory 0x10000 or higher. - -ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff - # (Header version 0x0203 or later) - # The highest safe address for - # the contents of an initrd - -kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment - #required for protected mode - #kernel -#ifdef CONFIG_RELOCATABLE -relocatable_kernel: .byte 1 -#else -relocatable_kernel: .byte 0 -#endif -pad2: .byte 0 -pad3: .word 0 - -cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, - #added with boot protocol - #version 2.06 - -# End of setup header ##################################################### - - .section ".inittext", "ax" -start_of_setup: -#ifdef SAFE_RESET_DISK_CONTROLLER -# Reset the disk controller. - movw $0x0000, %ax # Reset disk controller - movb $0x80, %dl # All disks - int $0x13 -#endif - -# We will have entired with %cs = %ds+0x20, normalize %cs so -# it is on par with the other segments. - pushw %ds - pushw $setup2 - lretw - -setup2: -# Force %es = %ds - movw %ds, %ax - movw %ax, %es - cld - -# Stack paranoia: align the stack and make sure it is good -# for both 16- and 32-bit references. In particular, if we -# were meant to have been using the full 16-bit segment, the -# caller might have set %sp to zero, which breaks %esp-based -# references. - andw $~3, %sp # dword align (might as well...) - jnz 1f - movw $0xfffc, %sp # Make sure we're not zero -1: movzwl %sp, %esp # Clear upper half of %esp - sti - -# Check signature at end of setup - cmpl $0x5a5aaa55, setup_sig - jne setup_bad - -# Zero the bss - movw $__bss_start, %di - movw $_end+3, %cx - xorl %eax, %eax - subw %di, %cx - shrw $2, %cx - rep; stosl - -# Jump to C code (should not return) - calll main - -# Setup corrupt somehow... -setup_bad: - movl $setup_corrupt, %eax - calll puts - # Fall through... - - .globl die - .type die, @function -die: - hlt - jmp die - - .size die, .-due - - .section ".initdata", "a" -setup_corrupt: - .byte 7 - .string "No setup signature found..." diff --git a/trunk/arch/i386/boot/main.c b/trunk/arch/i386/boot/main.c deleted file mode 100644 index 7f01f96c4fb8..000000000000 --- a/trunk/arch/i386/boot/main.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/main.c - * - * Main module for the real-mode kernel code - */ - -#include "boot.h" - -struct boot_params boot_params __attribute__((aligned(16))); - -char *HEAP = _end; -char *heap_end = _end; /* Default end of heap = no heap */ - -/* - * Copy the header into the boot parameter block. Since this - * screws up the old-style command line protocol, adjust by - * filling in the new-style command line pointer instead. - */ -#define OLD_CL_MAGIC 0xA33F -#define OLD_CL_ADDRESS 0x20 - -static void copy_boot_params(void) -{ - struct old_cmdline { - u16 cl_magic; - u16 cl_offset; - }; - const struct old_cmdline * const oldcmd = - (const struct old_cmdline *)OLD_CL_ADDRESS; - - BUILD_BUG_ON(sizeof boot_params != 4096); - memcpy(&boot_params.hdr, &hdr, sizeof hdr); - - if (!boot_params.hdr.cmd_line_ptr && - oldcmd->cl_magic == OLD_CL_MAGIC) { - /* Old-style command line protocol. */ - u16 cmdline_seg; - - /* Figure out if the command line falls in the region - of memory that an old kernel would have copied up - to 0x90000... */ - if (oldcmd->cl_offset < boot_params.hdr.setup_move_size) - cmdline_seg = ds(); - else - cmdline_seg = 0x9000; - - boot_params.hdr.cmd_line_ptr = - (cmdline_seg << 4) + oldcmd->cl_offset; - } -} - -/* - * Set the keyboard repeat rate to maximum. Unclear why this - * is done here; this might be possible to kill off as stale code. - */ -static void keyboard_set_repeat(void) -{ - u16 ax = 0x0305; - u16 bx = 0; - asm volatile("int $0x16" - : "+a" (ax), "+b" (bx) - : : "ecx", "edx", "esi", "edi"); -} - -/* - * Get Intel SpeedStep IST information. - */ -static void query_speedstep_ist(void) -{ - asm("int $0x15" - : "=a" (boot_params.speedstep_info[0]), - "=b" (boot_params.speedstep_info[1]), - "=c" (boot_params.speedstep_info[2]), - "=d" (boot_params.speedstep_info[3]) - : "a" (0x0000e980), /* IST Support */ - "d" (0x47534943)); /* Request value */ -} - -/* - * Tell the BIOS what CPU mode we intend to run in. - */ -static void set_bios_mode(void) -{ -#ifdef CONFIG_X86_64 - u32 eax, ebx; - - eax = 0xec00; - ebx = 2; - asm volatile("int $0x15" - : "+a" (eax), "+b" (ebx) - : : "ecx", "edx", "esi", "edi"); -#endif -} - -void main(void) -{ - /* First, copy the boot header into the "zeropage" */ - copy_boot_params(); - - /* End of heap check */ - if (boot_params.hdr.loadflags & CAN_USE_HEAP) { - heap_end = (char *)(boot_params.hdr.heap_end_ptr - +0x200-STACK_SIZE); - } else { - /* Boot protocol 2.00 only, no heap available */ - puts("WARNING: Ancient bootloader, some functionality " - "may be limited!\n"); - } - - /* Make sure we have all the proper CPU support */ - if (validate_cpu()) { - puts("Unable to boot - please use a kernel appropriate " - "for your CPU.\n"); - die(); - } - - /* Tell the BIOS what CPU mode we intend to run in. */ - set_bios_mode(); - - /* Detect memory layout */ - detect_memory(); - - /* Set keyboard repeat rate (why?) */ - keyboard_set_repeat(); - - /* Set the video mode */ - set_video(); - - /* Query MCA information */ - query_mca(); - - /* Voyager */ -#ifdef CONFIG_X86_VOYAGER - query_voyager(); -#endif - - /* Query SpeedStep IST information */ - query_speedstep_ist(); - - /* Query APM information */ -#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) - query_apm_bios(); -#endif - - /* Query EDD information */ -#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) - query_edd(); -#endif - /* Do the last things and invoke protected mode */ - go_to_protected_mode(); -} diff --git a/trunk/arch/i386/boot/mca.c b/trunk/arch/i386/boot/mca.c deleted file mode 100644 index 9b68bd1aef19..000000000000 --- a/trunk/arch/i386/boot/mca.c +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/mca.c - * - * Get the MCA system description table - */ - -#include "boot.h" - -int query_mca(void) -{ - u8 err; - u16 es, bx, len; - - asm("pushw %%es ; " - "int $0x15 ; " - "setc %0 ; " - "movw %%es, %1 ; " - "popw %%es" - : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx) - : "a" (0xc000)); - - if (err) - return -1; /* No MCA present */ - - set_fs(es); - len = rdfs16(bx); - - if (len > sizeof(boot_params.sys_desc_table)) - len = sizeof(boot_params.sys_desc_table); - - copy_from_fs(&boot_params.sys_desc_table, bx, len); - return 0; -} diff --git a/trunk/arch/i386/boot/memory.c b/trunk/arch/i386/boot/memory.c deleted file mode 100644 index 1a2e62db8bed..000000000000 --- a/trunk/arch/i386/boot/memory.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/memory.c - * - * Memory detection code - */ - -#include "boot.h" - -#define SMAP 0x534d4150 /* ASCII "SMAP" */ - -static int detect_memory_e820(void) -{ - u32 next = 0; - u32 size, id; - u8 err; - struct e820entry *desc = boot_params.e820_map; - - do { - size = sizeof(struct e820entry); - id = SMAP; - asm("int $0x15; setc %0" - : "=am" (err), "+b" (next), "+d" (id), "+c" (size), - "=m" (*desc) - : "D" (desc), "a" (0xe820)); - - if (err || id != SMAP) - break; - - boot_params.e820_entries++; - desc++; - } while (next && boot_params.e820_entries < E820MAX); - - return boot_params.e820_entries; -} - -static int detect_memory_e801(void) -{ - u16 ax, bx, cx, dx; - u8 err; - - bx = cx = dx = 0; - ax = 0xe801; - asm("stc; int $0x15; setc %0" - : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx)); - - if (err) - return -1; - - /* Do we really need to do this? */ - if (cx || dx) { - ax = cx; - bx = dx; - } - - if (ax > 15*1024) - return -1; /* Bogus! */ - - /* This ignores memory above 16MB if we have a memory hole - there. If someone actually finds a machine with a memory - hole at 16MB and no support for 0E820h they should probably - generate a fake e820 map. */ - boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax; - - return 0; -} - -static int detect_memory_88(void) -{ - u16 ax; - u8 err; - - ax = 0x8800; - asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax)); - - boot_params.screen_info.ext_mem_k = ax; - - return -err; -} - -int detect_memory(void) -{ - if (detect_memory_e820() > 0) - return 0; - - if (!detect_memory_e801()) - return 0; - - return detect_memory_88(); -} diff --git a/trunk/arch/i386/boot/pm.c b/trunk/arch/i386/boot/pm.c deleted file mode 100644 index 3fa53e15ed77..000000000000 --- a/trunk/arch/i386/boot/pm.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/pm.c - * - * Prepare the machine for transition to protected mode. - */ - -#include "boot.h" -#include - -/* - * Invoke the realmode switch hook if present; otherwise - * disable all interrupts. - */ -static void realmode_switch_hook(void) -{ - if (boot_params.hdr.realmode_swtch) { - asm volatile("lcallw *%0" - : : "m" (boot_params.hdr.realmode_swtch) - : "eax", "ebx", "ecx", "edx"); - } else { - asm volatile("cli"); - outb(0x80, 0x70); /* Disable NMI */ - io_delay(); - } -} - -/* - * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000. - * A bzImage kernel is loaded and runs at 0x100000. - */ -static void move_kernel_around(void) -{ - /* Note: rely on the compile-time option here rather than - the LOADED_HIGH flag. The Qemu kernel loader unconditionally - sets the loadflags to zero. */ -#ifndef __BIG_KERNEL__ - u16 dst_seg, src_seg; - u32 syssize; - - dst_seg = 0x1000 >> 4; - src_seg = 0x10000 >> 4; - syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraphs */ - - while (syssize) { - int paras = (syssize >= 0x1000) ? 0x1000 : syssize; - int dwords = paras << 2; - - asm volatile("pushw %%es ; " - "pushw %%ds ; " - "movw %1,%%es ; " - "movw %2,%%ds ; " - "xorw %%di,%%di ; " - "xorw %%si,%%si ; " - "rep;movsl ; " - "popw %%ds ; " - "popw %%es" - : "+c" (dwords) - : "rm" (dst_seg), "rm" (src_seg) - : "esi", "edi"); - - syssize -= paras; - dst_seg += paras; - src_seg += paras; - } -#endif -} - -/* - * Disable all interrupts at the legacy PIC. - */ -static void mask_all_interrupts(void) -{ - outb(0xff, 0xa1); /* Mask all interrupts on the seconday PIC */ - io_delay(); - outb(0xfb, 0x21); /* Mask all but cascade on the primary PIC */ - io_delay(); -} - -/* - * Reset IGNNE# if asserted in the FPU. - */ -static void reset_coprocessor(void) -{ - outb(0, 0xf0); - io_delay(); - outb(0, 0xf1); - io_delay(); -} - -/* - * Set up the GDT - */ -#define GDT_ENTRY(flags,base,limit) \ - (((u64)(base & 0xff000000) << 32) | \ - ((u64)flags << 40) | \ - ((u64)(limit & 0x00ff0000) << 32) | \ - ((u64)(base & 0x00ffff00) << 16) | \ - ((u64)(limit & 0x0000ffff))) - -struct gdt_ptr { - u16 len; - u32 ptr; -} __attribute__((packed)); - -static void setup_gdt(void) -{ - /* There are machines which are known to not boot with the GDT - being 8-byte unaligned. Intel recommends 16 byte alignment. */ - static const u64 boot_gdt[] __attribute__((aligned(16))) = { - /* CS: code, read/execute, 4 GB, base 0 */ - [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff), - /* DS: data, read/write, 4 GB, base 0 */ - [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), - }; - struct gdt_ptr gdt; - - gdt.len = sizeof(boot_gdt)-1; - gdt.ptr = (u32)&boot_gdt + (ds() << 4); - - asm volatile("lgdtl %0" : : "m" (gdt)); -} - -/* - * Set up the IDT - */ -static void setup_idt(void) -{ - static const struct gdt_ptr null_idt = {0, 0}; - asm volatile("lidtl %0" : : "m" (null_idt)); -} - -/* - * Actual invocation sequence - */ -void go_to_protected_mode(void) -{ - /* Hook before leaving real mode, also disables interrupts */ - realmode_switch_hook(); - - /* Move the kernel/setup to their final resting places */ - move_kernel_around(); - - /* Enable the A20 gate */ - if (enable_a20()) { - puts("A20 gate not responding, unable to boot...\n"); - die(); - } - - /* Reset coprocessor (IGNNE#) */ - reset_coprocessor(); - - /* Mask all interrupts in the PIC */ - mask_all_interrupts(); - - /* Actual transition to protected mode... */ - setup_idt(); - setup_gdt(); - protected_mode_jump(boot_params.hdr.code32_start, - (u32)&boot_params + (ds() << 4)); -} diff --git a/trunk/arch/i386/boot/pmjump.S b/trunk/arch/i386/boot/pmjump.S deleted file mode 100644 index 2e559233725a..000000000000 --- a/trunk/arch/i386/boot/pmjump.S +++ /dev/null @@ -1,54 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/pmjump.S - * - * The actual transition into protected mode - */ - -#include -#include - - .text - - .globl protected_mode_jump - .type protected_mode_jump, @function - - .code16 - -/* - * void protected_mode_jump(u32 entrypoint, u32 bootparams); - */ -protected_mode_jump: - xorl %ebx, %ebx # Flag to indicate this is a boot - movl %edx, %esi # Pointer to boot_params table - movl %eax, 2f # Patch ljmpl instruction - jmp 1f # Short jump to flush instruction q. - -1: - movw $__BOOT_DS, %cx - - movl %cr0, %edx - orb $1, %dl # Protected mode (PE) bit - movl %edx, %cr0 - - movw %cx, %ds - movw %cx, %es - movw %cx, %fs - movw %cx, %gs - movw %cx, %ss - - # Jump to the 32-bit entrypoint - .byte 0x66, 0xea # ljmpl opcode -2: .long 0 # offset - .word __BOOT_CS # segment - - .size protected_mode_jump, .-protected_mode_jump diff --git a/trunk/arch/i386/boot/printf.c b/trunk/arch/i386/boot/printf.c deleted file mode 100644 index 1a09f9309d3c..000000000000 --- a/trunk/arch/i386/boot/printf.c +++ /dev/null @@ -1,307 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/printf.c - * - * Oh, it's a waste of space, but oh-so-yummy for debugging. This - * version of printf() does not include 64-bit support. "Live with - * it." - * - */ - -#include "boot.h" - -static int skip_atoi(const char **s) -{ - int i = 0; - - while (isdigit(**s)) - i = i * 10 + *((*s)++) - '0'; - return i; -} - -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -#define do_div(n,base) ({ \ -int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) - -static char *number(char *str, long num, int base, int size, int precision, - int type) -{ - char c, sign, tmp[66]; - const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++] = '0'; - else - while (num != 0) - tmp[i++] = digits[do_div(num, base)]; - if (i > precision) - precision = i; - size -= precision; - if (!(type & (ZEROPAD + LEFT))) - while (size-- > 0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIAL) { - if (base == 8) - *str++ = '0'; - else if (base == 16) { - *str++ = '0'; - *str++ = digits[33]; - } - } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - return str; -} - -int vsprintf(char *buf, const char *fmt, va_list args) -{ - int len; - unsigned long num; - int i, base; - char *str; - const char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - - for (str = buf; *fmt; ++fmt) { - if (*fmt != '%') { - *str++ = *fmt; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': - flags |= LEFT; - goto repeat; - case '+': - flags |= PLUS; - goto repeat; - case ' ': - flags |= SPACE; - goto repeat; - case '#': - flags |= SPECIAL; - goto repeat; - case '0': - flags |= ZEROPAD; - goto repeat; - } - - /* get field width */ - field_width = -1; - if (isdigit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if (isdigit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - *str++ = ' '; - *str++ = (unsigned char)va_arg(args, int); - while (--field_width > 0) - *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - len = strnlen(s, precision); - - if (!(flags & LEFT)) - while (len < field_width--) - *str++ = ' '; - for (i = 0; i < len; ++i) - *str++ = *s++; - while (len < field_width--) - *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2 * sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, - (unsigned long)va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - case 'n': - if (qualifier == 'l') { - long *ip = va_arg(args, long *); - *ip = (str - buf); - } else { - int *ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - case '%': - *str++ = '%'; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; - } - if (qualifier == 'l') - num = va_arg(args, unsigned long); - else if (qualifier == 'h') { - num = (unsigned short)va_arg(args, int); - if (flags & SIGN) - num = (short)num; - } else if (flags & SIGN) - num = va_arg(args, int); - else - num = va_arg(args, unsigned int); - str = number(str, num, base, field_width, precision, flags); - } - *str = '\0'; - return str - buf; -} - -int sprintf(char *buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i = vsprintf(buf, fmt, args); - va_end(args); - return i; -} - -int printf(const char *fmt, ...) -{ - char printf_buf[1024]; - va_list args; - int printed; - - va_start(args, fmt); - printed = vsprintf(printf_buf, fmt, args); - va_end(args); - - puts(printf_buf); - - return printed; -} diff --git a/trunk/arch/i386/boot/setup.S b/trunk/arch/i386/boot/setup.S new file mode 100644 index 000000000000..6dbcc95b2120 --- /dev/null +++ b/trunk/arch/i386/boot/setup.S @@ -0,0 +1,1075 @@ +/* + * setup.S Copyright (C) 1991, 1992 Linus Torvalds + * + * setup.s is responsible for getting the system data from the BIOS, + * and putting them into the appropriate places in system memory. + * both setup.s and system has been loaded by the bootblock. + * + * This code asks the bios for memory/disk/other parameters, and + * puts them in a "safe" place: 0x90000-0x901FF, ie where the + * boot-block used to be. It is then up to the protected mode + * system to read them from there before the area is overwritten + * for buffer-blocks. + * + * Move PS/2 aux init code to psaux.c + * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 + * + * some changes and additional features by Christoph Niemann, + * March 1993/June 1994 (Christoph.Niemann@linux.org) + * + * add APM BIOS checking by Stephen Rothwell, May 1994 + * (sfr@canb.auug.org.au) + * + * High load stuff, initrd support and position independency + * by Hans Lermen & Werner Almesberger, February 1996 + * , + * + * Video handling moved to video.S by Martin Mares, March 1996 + * + * + * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david + * parsons) to avoid loadlin confusion, July 1997 + * + * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. + * + * + * Fix to work around buggy BIOSes which don't use carry bit correctly + * and/or report extended memory in CX/DX for e801h memory size detection + * call. As a result the kernel got wrong figures. The int15/e801h docs + * from Ralf Brown interrupt list seem to indicate AX/BX should be used + * anyway. So to avoid breaking many machines (presumably there was a reason + * to orginally use CX/DX instead of AX/BX), we do a kludge to see + * if CX/DX have been changed in the e801 call and if so use AX/BX . + * Michael Miller, April 2001 + * + * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes + * by Robert Schwebel, December 2001 + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Signature words to ensure LILO loaded us right */ +#define SIG1 0xAA55 +#define SIG2 0x5A5A + +INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way +SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). +SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment + # ... and the former contents of CS + +DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 + +.code16 +.globl begtext, begdata, begbss, endtext, enddata, endbss + +.text +begtext: +.data +begdata: +.bss +begbss: +.text + +start: + jmp trampoline + +# This is the setup header, and it must start at %cs:2 (old 0x9020:2) + + .ascii "HdrS" # header signature + .word 0x0206 # header version number (>= 0x0105) + # or else old loadlin-1.5 will fail) +realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +start_sys_seg: .word SYSSEG + .word kernel_version # pointing to kernel version string + # above section of header is compatible + # with loadlin-1.5 (header v1.5). Don't + # change it. + +type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, + # Bootlin, SYSLX, bootsect...) + # See Documentation/i386/boot.txt for + # assigned ids + +# flags, unused bits must be zero (RFU) bit within loadflags +loadflags: +LOADED_HIGH = 1 # If set, the kernel is loaded high +CAN_USE_HEAP = 0x80 # If set, the loader also has set + # heap_end_ptr to tell how much + # space behind setup.S can be used for + # heap purposes. + # Only the loader knows what is free +#ifndef __BIG_KERNEL__ + .byte 0 +#else + .byte LOADED_HIGH +#endif + +setup_move_size: .word 0x8000 # size to move, when setup is not + # loaded at 0x90000. We will move setup + # to 0x90000 then just before jumping + # into the kernel. However, only the + # loader knows how much data behind + # us also needs to be loaded. + +code32_start: # here loaders can put a different + # start address for 32-bit code. +#ifndef __BIG_KERNEL__ + .long 0x1000 # 0x1000 = default for zImage +#else + .long 0x100000 # 0x100000 = default for big kernel +#endif + +ramdisk_image: .long 0 # address of loaded ramdisk image + # Here the loader puts the 32-bit + # address where it loaded the image. + # This only will be read by the kernel. + +ramdisk_size: .long 0 # its size in bytes + +bootsect_kludge: + .long 0 # obsolete + +heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) + # space from here (exclusive) down to + # end of setup code can be used by setup + # for local heap purposes. + +pad1: .word 0 +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + +ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff + # (Header version 0x0203 or later) + # The highest safe address for + # the contents of an initrd + +kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment + #required for protected mode + #kernel +#ifdef CONFIG_RELOCATABLE +relocatable_kernel: .byte 1 +#else +relocatable_kernel: .byte 0 +#endif +pad2: .byte 0 +pad3: .word 0 + +cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, + #added with boot protocol + #version 2.06 + +trampoline: call start_of_setup + .align 16 + # The offset at this point is 0x240 + .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) +# End of setup header ##################################################### + +start_of_setup: +# Bootlin depends on this being done early + movw $0x01500, %ax + movb $0x81, %dl + int $0x13 + +#ifdef SAFE_RESET_DISK_CONTROLLER +# Reset the disk controller. + movw $0x0000, %ax + movb $0x80, %dl + int $0x13 +#endif + +# Set %ds = %cs, we know that SETUPSEG = %cs at this point + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds +# Check signature at end of setup + cmpw $SIG1, setup_sig1 + jne bad_sig + + cmpw $SIG2, setup_sig2 + jne bad_sig + + jmp good_sig1 + +# Routine to print asciiz string at ds:si +prtstr: + lodsb + andb %al, %al + jz fin + + call prtchr + jmp prtstr + +fin: ret + +# Space printing +prtsp2: call prtspc # Print double space +prtspc: movb $0x20, %al # Print single space (note: fall-thru) + +# Part of above routine, this one just prints ascii al +prtchr: pushw %ax + pushw %cx + movw $7,%bx + movw $0x01, %cx + movb $0x0e, %ah + int $0x10 + popw %cx + popw %ax + ret + +beep: movb $0x07, %al + jmp prtchr + +no_sig_mess: .string "No setup signature found ..." + +good_sig1: + jmp good_sig + +# We now have to find the rest of the setup code/data +bad_sig: + movw %cs, %ax # SETUPSEG + subw $DELTA_INITSEG, %ax # INITSEG + movw %ax, %ds + xorb %bh, %bh + movb (497), %bl # get setup sect from bootsect + subw $4, %bx # LILO loads 4 sectors of setup + shlw $8, %bx # convert to words (1sect=2^8 words) + movw %bx, %cx + shrw $3, %bx # convert to segment + addw $SYSSEG, %bx + movw %bx, %cs:start_sys_seg +# Move rest of setup code/data to here + movw $2048, %di # four sectors loaded by LILO + subw %si, %si + pushw %cs + popw %es + movw $SYSSEG, %ax + movw %ax, %ds + rep + movsw + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + cmpw $SIG1, setup_sig1 + jne no_sig + + cmpw $SIG2, setup_sig2 + jne no_sig + + jmp good_sig + +no_sig: + lea no_sig_mess, %si + call prtstr + +no_sig_loop: + hlt + jmp no_sig_loop + +good_sig: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds +# Check if an old loader tries to load a big-kernel + testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? + jz loader_ok # No, no danger for old loaders. + + cmpb $0, %cs:type_of_loader # Do we have a loader that + # can deal with us? + jnz loader_ok # Yes, continue. + + pushw %cs # No, we have an old loader, + popw %ds # die. + lea loader_panic_mess, %si + call prtstr + + jmp no_sig_loop + +loader_panic_mess: .string "Wrong loader, giving up..." + +# check minimum cpuid +# we do this here because it is the last place we can actually +# show a user visible error message. Later the video modus +# might be already messed up. +loader_ok: + call verify_cpu + testl %eax,%eax + jz cpu_ok + movw %cs,%ax # aka SETUPSEG + movw %ax,%ds + lea cpu_panic_mess,%si + call prtstr +1: jmp 1b + +cpu_panic_mess: + .asciz "PANIC: CPU too old for this kernel." + +#include "../kernel/verify_cpu.S" + +cpu_ok: +# Get memory size (extended mem, kB) + + xorl %eax, %eax + movl %eax, (0x1e0) +#ifndef STANDARD_MEMORY_BIOS_CALL + movb %al, (E820NR) +# Try three different memory detection schemes. First, try +# e820h, which lets us assemble a memory map, then try e801h, +# which returns a 32-bit memory size, and finally 88h, which +# returns 0-64m + +# method E820H: +# the memory map from hell. e820h returns memory classified into +# a whole bunch of different types, and allows memory holes and +# everything. We scan through this memory map and build a list +# of the first 32 memory areas, which we return at [E820MAP]. +# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. + +#define SMAP 0x534d4150 + +meme820: + xorl %ebx, %ebx # continuation counter + movw $E820MAP, %di # point into the whitelist + # so we can have the bios + # directly write into it. + +jmpe820: + movl $0x0000e820, %eax # e820, upper word zeroed + movl $SMAP, %edx # ascii 'SMAP' + movl $20, %ecx # size of the e820rec + pushw %ds # data record. + popw %es + int $0x15 # make the call + jc bail820 # fall to e801 if it fails + + cmpl $SMAP, %eax # check the return is `SMAP' + jne bail820 # fall to e801 if it fails + +# cmpl $1, 16(%di) # is this usable memory? +# jne again820 + + # If this is usable memory, we save it by simply advancing %di by + # sizeof(e820rec). + # +good820: + movb (E820NR), %al # up to 128 entries + cmpb $E820MAX, %al + jae bail820 + + incb (E820NR) + movw %di, %ax + addw $20, %ax + movw %ax, %di +again820: + cmpl $0, %ebx # check to see if + jne jmpe820 # %ebx is set to EOF +bail820: + + +# method E801H: +# memory size is in 1k chunksizes, to avoid confusing loadlin. +# we store the 0xe801 memory size in a completely different place, +# because it will most likely be longer than 16 bits. +# (use 1e0 because that's what Larry Augustine uses in his +# alternative new memory detection scheme, and it's sensible +# to write everything into the same place.) + +meme801: + stc # fix to work around buggy + xorw %cx,%cx # BIOSes which don't clear/set + xorw %dx,%dx # carry on pass/error of + # e801h memory size call + # or merely pass cx,dx though + # without changing them. + movw $0xe801, %ax + int $0x15 + jc mem88 + + cmpw $0x0, %cx # Kludge to handle BIOSes + jne e801usecxdx # which report their extended + cmpw $0x0, %dx # memory in AX/BX rather than + jne e801usecxdx # CX/DX. The spec I have read + movw %ax, %cx # seems to indicate AX/BX + movw %bx, %dx # are more reasonable anyway... + +e801usecxdx: + andl $0xffff, %edx # clear sign extend + shll $6, %edx # and go from 64k to 1k chunks + movl %edx, (0x1e0) # store extended memory size + andl $0xffff, %ecx # clear sign extend + addl %ecx, (0x1e0) # and add lower memory into + # total size. + +# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +# 64mb, depending on the bios) in ax. +mem88: + +#endif + movb $0x88, %ah + int $0x15 + movw %ax, (2) + +# Set the keyboard repeat rate to the max + movw $0x0305, %ax + xorw %bx, %bx + int $0x16 + +# Check for video adapter and its parameters and allow the +# user to browse video modes. + call video # NOTE: we need %ds pointing + # to bootsector + +# Get hd0 data... + xorw %ax, %ax + movw %ax, %ds + ldsw (4 * 0x41), %si + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + pushw %ax + movw %ax, %es + movw $0x0080, %di + movw $0x10, %cx + pushw %cx + cld + rep + movsb +# Get hd1 data... + xorw %ax, %ax + movw %ax, %ds + ldsw (4 * 0x46), %si + popw %cx + popw %es + movw $0x0090, %di + rep + movsb +# Check that there IS a hd1 :-) + movw $0x01500, %ax + movb $0x81, %dl + int $0x13 + jc no_disk1 + + cmpb $3, %ah + je is_disk1 + +no_disk1: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + xorw %ax, %ax + cld + rep + stosb +is_disk1: +# check for Micro Channel (MCA) bus + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds + xorw %ax, %ax + movw %ax, (0xa0) # set table length to 0 + movb $0xc0, %ah + stc + int $0x15 # moves feature table to es:bx + jc no_mca + + pushw %ds + movw %es, %ax + movw %ax, %ds + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %es + movw %bx, %si + movw $0xa0, %di + movw (%si), %cx + addw $2, %cx # table length is a short + cmpw $0x10, %cx + jc sysdesc_ok + + movw $0x10, %cx # we keep only first 16 bytes +sysdesc_ok: + rep + movsb + popw %ds +no_mca: +#ifdef CONFIG_X86_VOYAGER + movb $0xff, 0x40 # flag on config found + movb $0xc0, %al + mov $0xff, %ah + int $0x15 # put voyager config info at es:di + jc no_voyager + movw $0x40, %si # place voyager info in apm table + cld + movw $7, %cx +voyager_rep: + movb %es:(%di), %al + movb %al,(%si) + incw %di + incw %si + decw %cx + jnz voyager_rep +no_voyager: +#endif +# Check for PS/2 pointing device + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds + movb $0, (0x1ff) # default is no pointing device + int $0x11 # int 0x11: equipment list + testb $0x04, %al # check if mouse installed + jz no_psmouse + + movb $0xAA, (0x1ff) # device present +no_psmouse: + +#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) + movl $0x0000E980, %eax # IST Support + movl $0x47534943, %edx # Request value + int $0x15 + + movl %eax, (96) + movl %ebx, (100) + movl %ecx, (104) + movl %edx, (108) +#endif + +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +# Then check for an APM BIOS... + # %ds points to the bootsector + movw $0, 0x40 # version = 0 means no APM BIOS + movw $0x05300, %ax # APM BIOS installation check + xorw %bx, %bx + int $0x15 + jc done_apm_bios # Nope, no APM BIOS + + cmpw $0x0504d, %bx # Check for "PM" signature + jne done_apm_bios # No signature, no APM BIOS + + andw $0x02, %cx # Is 32 bit supported? + je done_apm_bios # No 32-bit, no (good) APM BIOS + + movw $0x05304, %ax # Disconnect first just in case + xorw %bx, %bx + int $0x15 # ignore return code + movw $0x05303, %ax # 32 bit connect + xorl %ebx, %ebx + xorw %cx, %cx # paranoia :-) + xorw %dx, %dx # ... + xorl %esi, %esi # ... + xorw %di, %di # ... + int $0x15 + jc no_32_apm_bios # Ack, error. + + movw %ax, (66) # BIOS code segment + movl %ebx, (68) # BIOS entry point offset + movw %cx, (72) # BIOS 16 bit code segment + movw %dx, (74) # BIOS data segment + movl %esi, (78) # BIOS code segment lengths + movw %di, (82) # BIOS data segment length +# Redo the installation check as the 32 bit connect +# modifies the flags returned on some BIOSs + movw $0x05300, %ax # APM BIOS installation check + xorw %bx, %bx + xorw %cx, %cx # paranoia + int $0x15 + jc apm_disconnect # error -> shouldn't happen + + cmpw $0x0504d, %bx # check for "PM" signature + jne apm_disconnect # no sig -> shouldn't happen + + movw %ax, (64) # record the APM BIOS version + movw %cx, (76) # and flags + jmp done_apm_bios + +apm_disconnect: # Tidy up + movw $0x05304, %ax # Disconnect + xorw %bx, %bx + int $0x15 # ignore return code + + jmp done_apm_bios + +no_32_apm_bios: + andw $0xfffd, (76) # remove 32 bit support bit +done_apm_bios: +#endif + +#include "edd.S" + +# Now we want to move to protected mode ... + cmpw $0, %cs:realmode_swtch + jz rmodeswtch_normal + + lcall *%cs:realmode_swtch + + jmp rmodeswtch_end + +rmodeswtch_normal: + pushw %cs + call default_switch + +rmodeswtch_end: +# Now we move the system to its rightful place ... but we check if we have a +# big-kernel. In that case we *must* not move it ... + testb $LOADED_HIGH, %cs:loadflags + jz do_move0 # .. then we have a normal low + # loaded zImage + # .. or else we have a high + # loaded bzImage + jmp end_move # ... and we skip moving + +do_move0: + movw $0x100, %ax # start of destination segment + movw %cs, %bp # aka SETUPSEG + subw $DELTA_INITSEG, %bp # aka INITSEG + movw %cs:start_sys_seg, %bx # start of source segment + cld +do_move: + movw %ax, %es # destination segment + incb %ah # instead of add ax,#0x100 + movw %bx, %ds # source segment + addw $0x100, %bx + subw %di, %di + subw %si, %si + movw $0x800, %cx + rep + movsw + cmpw %bp, %bx # assume start_sys_seg > 0x200, + # so we will perhaps read one + # page more than needed, but + # never overwrite INITSEG + # because destination is a + # minimum one page below source + jb do_move + +end_move: +# then we load the segment descriptors + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + +# Check whether we need to be downward compatible with version <=201 + cmpl $0, cmd_line_ptr + jne end_move_self # loader uses version >=202 features + cmpb $0x20, type_of_loader + je end_move_self # bootsect loader, we know of it + +# Boot loader doesnt support boot protocol version 2.02. +# If we have our code not at 0x90000, we need to move it there now. +# We also then need to move the params behind it (commandline) +# Because we would overwrite the code on the current IP, we move +# it in two steps, jumping high after the first one. + movw %cs, %ax + cmpw $SETUPSEG, %ax + je end_move_self + + cli # make sure we really have + # interrupts disabled ! + # because after this the stack + # should not be used + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ss, %dx + cmpw %ax, %dx + jb move_self_1 + + addw $INITSEG, %dx + subw %ax, %dx # this will go into %ss after + # the move +move_self_1: + movw %ax, %ds + movw $INITSEG, %ax # real INITSEG + movw %ax, %es + movw %cs:setup_move_size, %cx + std # we have to move up, so we use + # direction down because the + # areas may overlap + movw %cx, %di + decw %di + movw %di, %si + subw $move_self_here+0x200, %cx + rep + movsb + ljmp $SETUPSEG, $move_self_here + +move_self_here: + movw $move_self_here+0x200, %cx + rep + movsb + movw $SETUPSEG, %ax + movw %ax, %ds + movw %dx, %ss +end_move_self: # now we are at the right place + +# +# Enable A20. This is at the very best an annoying procedure. +# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin. +# AMD Elan bug fix by Robert Schwebel. +# + +#if defined(CONFIG_X86_ELAN) + movb $0x02, %al # alternate A20 gate + outb %al, $0x92 # this works on SC410/SC520 +a20_elan_wait: + call a20_test + jz a20_elan_wait + jmp a20_done +#endif + + +A20_TEST_LOOPS = 32 # Iterations per wait +A20_ENABLE_LOOPS = 255 # Total loops to try + + +#ifndef CONFIG_X86_VOYAGER +a20_try_loop: + + # First, see if we are on a system with no A20 gate. +a20_none: + call a20_test + jnz a20_done + + # Next, try the BIOS (INT 0x15, AX=0x2401) +a20_bios: + movw $0x2401, %ax + pushfl # Be paranoid about flags + int $0x15 + popfl + + call a20_test + jnz a20_done + + # Try enabling A20 through the keyboard controller +#endif /* CONFIG_X86_VOYAGER */ +a20_kbc: + call empty_8042 + +#ifndef CONFIG_X86_VOYAGER + call a20_test # Just in case the BIOS worked + jnz a20_done # but had a delayed reaction. +#endif + + movb $0xD1, %al # command write + outb %al, $0x64 + call empty_8042 + + movb $0xDF, %al # A20 on + outb %al, $0x60 + call empty_8042 + +#ifndef CONFIG_X86_VOYAGER + # Wait until a20 really *is* enabled; it can take a fair amount of + # time on certain systems; Toshiba Tecras are known to have this + # problem. +a20_kbc_wait: + xorw %cx, %cx +a20_kbc_wait_loop: + call a20_test + jnz a20_done + loop a20_kbc_wait_loop + + # Final attempt: use "configuration port A" +a20_fast: + inb $0x92, %al # Configuration Port A + orb $0x02, %al # "fast A20" version + andb $0xFE, %al # don't accidentally reset + outb %al, $0x92 + + # Wait for configuration port A to take effect +a20_fast_wait: + xorw %cx, %cx +a20_fast_wait_loop: + call a20_test + jnz a20_done + loop a20_fast_wait_loop + + # A20 is still not responding. Try frobbing it again. + # + decb (a20_tries) + jnz a20_try_loop + + movw $a20_err_msg, %si + call prtstr + +a20_die: + hlt + jmp a20_die + +a20_tries: + .byte A20_ENABLE_LOOPS + +a20_err_msg: + .ascii "linux: fatal error: A20 gate not responding!" + .byte 13, 10, 0 + + # If we get here, all is good +a20_done: + +#endif /* CONFIG_X86_VOYAGER */ +# set up gdt and idt and 32bit start address + lidt idt_48 # load idt with 0,0 + xorl %eax, %eax # Compute gdt_base + movw %ds, %ax # (Convert %ds:gdt to a linear ptr) + shll $4, %eax + addl %eax, code32 + addl $gdt, %eax + movl %eax, (gdt_48+2) + lgdt gdt_48 # load gdt with whatever is + # appropriate + +# make sure any possible coprocessor is properly reset.. + xorw %ax, %ax + outb %al, $0xf0 + call delay + + outb %al, $0xf1 + call delay + +# well, that went ok, I hope. Now we mask all interrupts - the rest +# is done in init_IRQ(). + movb $0xFF, %al # mask all interrupts for now + outb %al, $0xA1 + call delay + + movb $0xFB, %al # mask all irq's but irq2 which + outb %al, $0x21 # is cascaded + +# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't +# need no steenking BIOS anyway (except for the initial loading :-). +# The BIOS-routine wants lots of unnecessary data, and it's less +# "interesting" anyway. This is how REAL programmers do it. +# +# Well, now's the time to actually move into protected mode. To make +# things as simple as possible, we do no register set-up or anything, +# we let the gnu-compiled 32-bit programs do that. We just jump to +# absolute address 0x1000 (or the loader supplied one), +# in 32-bit protected mode. +# +# Note that the short jump isn't strictly needed, although there are +# reasons why it might be a good idea. It won't hurt in any case. + movw $1, %ax # protected mode (PE) bit + lmsw %ax # This is it! + jmp flush_instr + +flush_instr: + xorw %bx, %bx # Flag to indicate a boot + xorl %esi, %esi # Pointer to real-mode code + movw %cs, %si + subw $DELTA_INITSEG, %si + shll $4, %esi # Convert to 32-bit pointer + +# jump to startup_32 in arch/i386/boot/compressed/head.S +# +# NOTE: For high loaded big kernels we need a +# jmpi 0x100000,__BOOT_CS +# +# but we yet haven't reloaded the CS register, so the default size +# of the target offset still is 16 bit. +# However, using an operand prefix (0x66), the CPU will properly +# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference +# Manual, Mixing 16-bit and 32-bit code, page 16-6) + + .byte 0x66, 0xea # prefix + jmpi-opcode +code32: .long startup_32 # will be set to %cs+startup_32 + .word __BOOT_CS +.code32 +startup_32: + movl $(__BOOT_DS), %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + xorl %eax, %eax +1: incl %eax # check that A20 really IS enabled + movl %eax, 0x00000000 # loop forever if it isn't + cmpl %eax, 0x00100000 + je 1b + + # Jump to the 32bit entry point + jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi) +.code16 + +# Here's a bunch of information about your current kernel.. +kernel_version: .ascii UTS_RELEASE + .ascii " (" + .ascii LINUX_COMPILE_BY + .ascii "@" + .ascii LINUX_COMPILE_HOST + .ascii ") " + .ascii UTS_VERSION + .byte 0 + +# This is the default real mode switch routine. +# to be called just before protected mode transition +default_switch: + cli # no interrupts allowed ! + movb $0x80, %al # disable NMI for bootup + # sequence + outb %al, $0x70 + lret + + +#ifndef CONFIG_X86_VOYAGER +# This routine tests whether or not A20 is enabled. If so, it +# exits with zf = 0. +# +# The memory address used, 0x200, is the int $0x80 vector, which +# should be safe. + +A20_TEST_ADDR = 4*0x80 + +a20_test: + pushw %cx + pushw %ax + xorw %cx, %cx + movw %cx, %fs # Low memory + decw %cx + movw %cx, %gs # High memory area + movw $A20_TEST_LOOPS, %cx + movw %fs:(A20_TEST_ADDR), %ax + pushw %ax +a20_test_wait: + incw %ax + movw %ax, %fs:(A20_TEST_ADDR) + call delay # Serialize and make delay constant + cmpw %gs:(A20_TEST_ADDR+0x10), %ax + loope a20_test_wait + + popw %fs:(A20_TEST_ADDR) + popw %ax + popw %cx + ret + +#endif /* CONFIG_X86_VOYAGER */ + +# This routine checks that the keyboard command queue is empty +# (after emptying the output buffers) +# +# Some machines have delusions that the keyboard buffer is always full +# with no keyboard attached... +# +# If there is no keyboard controller, we will usually get 0xff +# to all the reads. With each IO taking a microsecond and +# a timeout of 100,000 iterations, this can take about half a +# second ("delay" == outb to port 0x80). That should be ok, +# and should also be plenty of time for a real keyboard controller +# to empty. +# + +empty_8042: + pushl %ecx + movl $100000, %ecx + +empty_8042_loop: + decl %ecx + jz empty_8042_end_loop + + call delay + + inb $0x64, %al # 8042 status port + testb $1, %al # output buffer? + jz no_output + + call delay + inb $0x60, %al # read it + jmp empty_8042_loop + +no_output: + testb $2, %al # is input buffer full? + jnz empty_8042_loop # yes - loop +empty_8042_end_loop: + popl %ecx + ret + +# Read the cmos clock. Return the seconds in al +gettime: + pushw %cx + movb $0x02, %ah + int $0x1a + movb %dh, %al # %dh contains the seconds + andb $0x0f, %al + movb %dh, %ah + movb $0x04, %cl + shrb %cl, %ah + aad + popw %cx + ret + +# Delay is needed after doing I/O +delay: + outb %al,$0x80 + ret + +# Descriptor tables +# +# NOTE: The intel manual says gdt should be sixteen bytes aligned for +# efficiency reasons. However, there are machines which are known not +# to boot with misaligned GDTs, so alter this at your peril! If you alter +# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two +# empty GDT entries (one for NULL and one reserved). +# +# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is +# true for the Voyager Quad CPU card which will not boot without +# This directive. 16 byte aligment is recommended by intel. +# + .align 16 +gdt: + .fill GDT_ENTRY_BOOT_CS,8,0 + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9A00 # code read/exec + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9200 # data read/write + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) +gdt_end: + .align 4 + + .word 0 # alignment byte +idt_48: + .word 0 # idt limit = 0 + .word 0, 0 # idt base = 0L + + .word 0 # alignment byte +gdt_48: + .word gdt_end - gdt - 1 # gdt limit + .word 0, 0 # gdt base (filled in later) + +# Include video setup & detection code + +#include "video.S" + +# Setup signature -- must be last +setup_sig1: .word SIG1 +setup_sig2: .word SIG2 + +# After this point, there is some free space which is used by the video mode +# handling code to store the temporary mode table (not used by the kernel). + +modelist: + +.text +endtext: +.data +enddata: +.bss +endbss: diff --git a/trunk/arch/i386/boot/setup.ld b/trunk/arch/i386/boot/setup.ld deleted file mode 100644 index df9234b3a5e0..000000000000 --- a/trunk/arch/i386/boot/setup.ld +++ /dev/null @@ -1,54 +0,0 @@ -/* - * setup.ld - * - * Linker script for the i386 setup code - */ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) - -SECTIONS -{ - . = 0; - .bstext : { *(.bstext) } - .bsdata : { *(.bsdata) } - - . = 497; - .header : { *(.header) } - .inittext : { *(.inittext) } - .initdata : { *(.initdata) } - .text : { *(.text*) } - - . = ALIGN(16); - .rodata : { *(.rodata*) } - - .videocards : { - video_cards = .; - *(.videocards) - video_cards_end = .; - } - - . = ALIGN(16); - .data : { *(.data*) } - - .signature : { - setup_sig = .; - LONG(0x5a5aaa55) - } - - - . = ALIGN(16); - .bss : - { - __bss_start = .; - *(.bss) - __bss_end = .; - } - . = ALIGN(16); - _end = .; - - /DISCARD/ : { *(.note*) } - - . = ASSERT(_end <= 0x8000, "Setup too big!"); - . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); -} diff --git a/trunk/arch/i386/boot/string.c b/trunk/arch/i386/boot/string.c deleted file mode 100644 index 481a22097781..000000000000 --- a/trunk/arch/i386/boot/string.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/string.c - * - * Very basic string functions - */ - -#include "boot.h" - -int strcmp(const char *str1, const char *str2) -{ - const unsigned char *s1 = (const unsigned char *)str1; - const unsigned char *s2 = (const unsigned char *)str2; - int delta = 0; - - while (*s1 || *s2) { - delta = *s2 - *s1; - if (delta) - return delta; - s1++; - s2++; - } - return 0; -} - -size_t strnlen(const char *s, size_t maxlen) -{ - const char *es = s; - while (*es && maxlen) { - es++; - maxlen--; - } - - return (es - s); -} - -unsigned int atou(const char *s) -{ - unsigned int i = 0; - while (isdigit(*s)) - i = i * 10 + (*s++ - '0'); - return i; -} diff --git a/trunk/arch/i386/boot/tools/build.c b/trunk/arch/i386/boot/tools/build.c index 886f47d8a488..05798419a6a9 100644 --- a/trunk/arch/i386/boot/tools/build.c +++ b/trunk/arch/i386/boot/tools/build.c @@ -1,12 +1,13 @@ /* * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1997 Martin Mares - * Copyright (C) 2007 H. Peter Anvin */ /* * This file builds a disk-image from three different files: * + * - bootsect: compatibility mbr which prints an error message if + * someone tries to boot the kernel directly. * - setup: 8086 machine code, sets up system parm * - system: 80386 code for actual system * @@ -20,7 +21,6 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 * Cross compiling fixes by Gertjan van Wingerde, July 1996 * Rewritten by Martin Mares, April 1997 - * Substantially overhauled by H. Peter Anvin, April 2007 */ #include @@ -32,25 +32,23 @@ #include #include #include -#include #include -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long u32; #define DEFAULT_MAJOR_ROOT 0 #define DEFAULT_MINOR_ROOT 0 -/* Minimal number of setup sectors */ -#define SETUP_SECT_MIN 5 -#define SETUP_SECT_MAX 64 +/* Minimal number of setup sectors (see also bootsect.S) */ +#define SETUP_SECTS 4 -/* This must be large enough to hold the entire setup */ -u8 buf[SETUP_SECT_MAX*512]; +byte buf[1024]; +int fd; int is_big_kernel; -static void die(const char * str, ...) +void die(const char * str, ...) { va_list args; va_start(args, str); @@ -59,9 +57,15 @@ static void die(const char * str, ...) exit(1); } -static void usage(void) +void file_open(const char *name) { - die("Usage: build [-b] setup system [rootdev] [> image]"); + if ((fd = open(name, O_RDONLY, 0)) < 0) + die("Unable to open `%s': %m", name); +} + +void usage(void) +{ + die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); } int main(int argc, char ** argv) @@ -69,30 +73,27 @@ int main(int argc, char ** argv) unsigned int i, sz, setup_sectors; int c; u32 sys_size; - u8 major_root, minor_root; + byte major_root, minor_root; struct stat sb; - FILE *file; - int fd; - void *kernel; if (argc > 2 && !strcmp(argv[1], "-b")) { is_big_kernel = 1; argc--, argv++; } - if ((argc < 3) || (argc > 4)) + if ((argc < 4) || (argc > 5)) usage(); - if (argc > 3) { - if (!strcmp(argv[3], "CURRENT")) { + if (argc > 4) { + if (!strcmp(argv[4], "CURRENT")) { if (stat("/", &sb)) { perror("/"); die("Couldn't stat /"); } major_root = major(sb.st_dev); minor_root = minor(sb.st_dev); - } else if (strcmp(argv[3], "FLOPPY")) { - if (stat(argv[3], &sb)) { - perror(argv[3]); + } else if (strcmp(argv[4], "FLOPPY")) { + if (stat(argv[4], &sb)) { + perror(argv[4]); die("Couldn't stat root device."); } major_root = major(sb.st_rdev); @@ -107,62 +108,79 @@ int main(int argc, char ** argv) } fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); - /* Copy the setup code */ - file = fopen(argv[1], "r"); - if (!file) - die("Unable to open `%s': %m", argv[1]); - c = fread(buf, 1, sizeof(buf), file); - if (ferror(file)) - die("read-error on `setup'"); - if (c < 1024) - die("The setup must be at least 1024 bytes"); + file_open(argv[1]); + i = read(fd, buf, sizeof(buf)); + fprintf(stderr,"Boot sector %d bytes.\n",i); + if (i != 512) + die("Boot block must be exactly 512 bytes"); if (buf[510] != 0x55 || buf[511] != 0xaa) die("Boot block hasn't got boot flag (0xAA55)"); - fclose(file); - - /* Pad unused space with zeros */ - setup_sectors = (c + 511) / 512; - if (setup_sectors < SETUP_SECT_MIN) - setup_sectors = SETUP_SECT_MIN; - i = setup_sectors*512; - memset(buf+c, 0, i-c); - - /* Set the default root device */ buf[508] = minor_root; buf[509] = major_root; + if (write(1, buf, 512) != 512) + die("Write call failed"); + close (fd); + + file_open(argv[2]); /* Copy the setup code */ + for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) + if (write(1, buf, c) != c) + die("Write call failed"); + if (c != 0) + die("read-error on `setup'"); + close (fd); + + setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ + /* for compatibility with ancient versions of LILO. */ + if (setup_sectors < SETUP_SECTS) + setup_sectors = SETUP_SECTS; + fprintf(stderr, "Setup is %d bytes.\n", i); + memset(buf, 0, sizeof(buf)); + while (i < setup_sectors * 512) { + c = setup_sectors * 512 - i; + if (c > sizeof(buf)) + c = sizeof(buf); + if (write(1, buf, c) != c) + die("Write call failed"); + i += c; + } - fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); - - /* Open and stat the kernel file */ - fd = open(argv[2], O_RDONLY); - if (fd < 0) - die("Unable to open `%s': %m", argv[2]); - if (fstat(fd, &sb)) - die("Unable to stat `%s': %m", argv[2]); + file_open(argv[3]); + if (fstat (fd, &sb)) + die("Unable to stat `%s': %m", argv[3]); sz = sb.st_size; - fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); - kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); - if (kernel == MAP_FAILED) - die("Unable to mmap '%s': %m", argv[2]); + fprintf (stderr, "System is %d kB\n", sz/1024); sys_size = (sz + 15) / 16; if (!is_big_kernel && sys_size > DEF_SYSSIZE) die("System is too big. Try using bzImage or modules."); - - /* Patch the setup code with the appropriate size parameters */ - buf[0x1f1] = setup_sectors-1; - buf[0x1f4] = sys_size; - buf[0x1f5] = sys_size >> 8; - buf[0x1f6] = sys_size >> 16; - buf[0x1f7] = sys_size >> 24; - - if (fwrite(buf, 1, i, stdout) != i) - die("Writing setup failed"); - - /* Copy the kernel code */ - if (fwrite(kernel, 1, sz, stdout) != sz) - die("Writing kernel failed"); + while (sz > 0) { + int l, n; + + l = (sz > sizeof(buf)) ? sizeof(buf) : sz; + if ((n=read(fd, buf, l)) != l) { + if (n < 0) + die("Error reading %s: %m", argv[3]); + else + die("%s: Unexpected EOF", argv[3]); + } + if (write(1, buf, l) != l) + die("Write failed"); + sz -= l; + } close(fd); - /* Everything is OK */ - return 0; + if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ + die("Output: seek failed"); + buf[0] = setup_sectors; + if (write(1, buf, 1) != 1) + die("Write of setup sector count failed"); + if (lseek(1, 500, SEEK_SET) != 500) + die("Output: seek failed"); + buf[0] = (sys_size & 0xff); + buf[1] = ((sys_size >> 8) & 0xff); + buf[2] = ((sys_size >> 16) & 0xff); + buf[3] = ((sys_size >> 24) & 0xff); + if (write(1, buf, 4) != 4) + die("Write of image length failed"); + + return 0; /* Everything is OK */ } diff --git a/trunk/arch/i386/boot/tty.c b/trunk/arch/i386/boot/tty.c deleted file mode 100644 index a8db78736b02..000000000000 --- a/trunk/arch/i386/boot/tty.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/tty.c - * - * Very simple screen I/O - * XXX: Probably should add very simple serial I/O? - */ - -#include "boot.h" - -/* - * These functions are in .inittext so they can be used to signal - * error during initialization. - */ - -void __attribute__((section(".inittext"))) putchar(int ch) -{ - unsigned char c = ch; - - if (c == '\n') - putchar('\r'); /* \n -> \r\n */ - - /* int $0x10 is known to have bugs involving touching registers - it shouldn't. Be extra conservative... */ - asm volatile("pushal; int $0x10; popal" - : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); -} - -void __attribute__((section(".inittext"))) puts(const char *str) -{ - int n = 0; - while (*str) { - putchar(*str++); - n++; - } -} - -/* - * Read the CMOS clock through the BIOS, and return the - * seconds in BCD. - */ - -static u8 gettime(void) -{ - u16 ax = 0x0200; - u16 cx, dx; - - asm("int $0x1a" - : "+a" (ax), "=c" (cx), "=d" (dx) - : : "ebx", "esi", "edi"); - - return dx >> 8; -} - -/* - * Read from the keyboard - */ -int getchar(void) -{ - u16 ax = 0; - asm("int $0x16" : "+a" (ax)); - - return ax & 0xff; -} - -static int kbd_pending(void) -{ - u8 pending; - asm("int $0x16; setnz %0" - : "=rm" (pending) - : "a" (0x0100)); - return pending; -} - -void kbd_flush(void) -{ - for (;;) { - if (!kbd_pending()) - break; - getchar(); - } -} - -int getchar_timeout(void) -{ - int cnt = 30; - int t0, t1; - - t0 = gettime(); - - while (cnt) { - if (kbd_pending()) - return getchar(); - - t1 = gettime(); - if (t0 != t1) { - cnt--; - t0 = t1; - } - } - - return 0; /* Timeout! */ -} diff --git a/trunk/arch/i386/boot/version.c b/trunk/arch/i386/boot/version.c deleted file mode 100644 index c61462f7d9a7..000000000000 --- a/trunk/arch/i386/boot/version.c +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/version.c - * - * Kernel version string - */ - -#include "boot.h" -#include -#include - -const char kernel_version[] = - UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " - UTS_VERSION; diff --git a/trunk/arch/i386/boot/vesa.h b/trunk/arch/i386/boot/vesa.h deleted file mode 100644 index ff5b73cd406f..000000000000 --- a/trunk/arch/i386/boot/vesa.h +++ /dev/null @@ -1,79 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 1999-2007 H. Peter Anvin - All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, Inc., 53 Temple Place Ste 330, - * Boston MA 02111-1307, USA; either version 2 of the License, or - * (at your option) any later version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- */ - -#ifndef BOOT_VESA_H -#define BOOT_VESA_H - -typedef struct { - u16 off, seg; -} far_ptr; - -/* VESA General Information table */ -struct vesa_general_info { - u32 signature; /* 0 Magic number = "VESA" */ - u16 version; /* 4 */ - far_ptr vendor_string; /* 6 */ - u32 capabilities; /* 10 */ - far_ptr video_mode_ptr; /* 14 */ - u16 total_memory; /* 18 */ - - u16 oem_software_rev; /* 20 */ - far_ptr oem_vendor_name_ptr; /* 22 */ - far_ptr oem_product_name_ptr; /* 26 */ - far_ptr oem_product_rev_ptr; /* 30 */ - - u8 reserved[222]; /* 34 */ - u8 oem_data[256]; /* 256 */ -} __attribute__ ((packed)); - -#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) -#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24)) - -struct vesa_mode_info { - u16 mode_attr; /* 0 */ - u8 win_attr[2]; /* 2 */ - u16 win_grain; /* 4 */ - u16 win_size; /* 6 */ - u16 win_seg[2]; /* 8 */ - far_ptr win_scheme; /* 12 */ - u16 logical_scan; /* 16 */ - - u16 h_res; /* 18 */ - u16 v_res; /* 20 */ - u8 char_width; /* 22 */ - u8 char_height; /* 23 */ - u8 memory_planes; /* 24 */ - u8 bpp; /* 25 */ - u8 banks; /* 26 */ - u8 memory_layout; /* 27 */ - u8 bank_size; /* 28 */ - u8 image_planes; /* 29 */ - u8 page_function; /* 30 */ - - u8 rmask; /* 31 */ - u8 rpos; /* 32 */ - u8 gmask; /* 33 */ - u8 gpos; /* 34 */ - u8 bmask; /* 35 */ - u8 bpos; /* 36 */ - u8 resv_mask; /* 37 */ - u8 resv_pos; /* 38 */ - u8 dcm_info; /* 39 */ - - u32 lfb_ptr; /* 40 Linear frame buffer address */ - u32 offscreen_ptr; /* 44 Offscreen memory address */ - u16 offscreen_size; /* 48 */ - - u8 reserved[206]; /* 50 */ -} __attribute__ ((packed)); - -#endif /* LIB_SYS_VESA_H */ diff --git a/trunk/arch/i386/boot/video-bios.c b/trunk/arch/i386/boot/video-bios.c deleted file mode 100644 index afea46c500cc..000000000000 --- a/trunk/arch/i386/boot/video-bios.c +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/video-bios.c - * - * Standard video BIOS modes - * - * We have two options for this; silent and scanned. - */ - -#include "boot.h" -#include "video.h" - -__videocard video_bios; - -/* Set a conventional BIOS mode */ -static int set_bios_mode(u8 mode); - -static int bios_set_mode(struct mode_info *mi) -{ - return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS); -} - -static int set_bios_mode(u8 mode) -{ - u16 ax; - u8 new_mode; - - ax = mode; /* AH=0x00 Set Video Mode */ - asm volatile(INT10 - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); - - ax = 0x0f00; /* Get Current Video Mode */ - asm volatile(INT10 - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); - - do_restore = 1; /* Assume video contents was lost */ - new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */ - - if (new_mode == mode) - return 0; /* Mode change OK */ - - if (new_mode != boot_params.screen_info.orig_video_mode) { - /* Mode setting failed, but we didn't end up where we - started. That's bad. Try to revert to the original - video mode. */ - ax = boot_params.screen_info.orig_video_mode; - asm volatile(INT10 - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); - } - return -1; -} - -static int bios_probe(void) -{ - u8 mode; - u8 saved_mode = boot_params.screen_info.orig_video_mode; - u16 crtc; - struct mode_info *mi; - int nmodes = 0; - - if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA) - return 0; - - set_fs(0); - crtc = vga_crtc(); - - video_bios.modes = GET_HEAP(struct mode_info, 0); - - for (mode = 0x14; mode <= 0x7f; mode++) { - if (heap_free() < sizeof(struct mode_info)) - break; - - if (mode_defined(VIDEO_FIRST_BIOS+mode)) - continue; - - if (set_bios_mode(mode)) - continue; - - /* Try to verify that it's a text mode. */ - - /* Attribute Controller: make graphics controller disabled */ - if (in_idx(0x3c0, 0x10) & 0x01) - continue; - - /* Graphics Controller: verify Alpha addressing enabled */ - if (in_idx(0x3ce, 0x06) & 0x01) - continue; - - /* CRTC cursor location low should be zero(?) */ - if (in_idx(crtc, 0x0f)) - continue; - - mi = GET_HEAP(struct mode_info, 1); - mi->mode = VIDEO_FIRST_BIOS+mode; - mi->x = rdfs16(0x44a); - mi->y = rdfs8(0x484)+1; - nmodes++; - } - - set_bios_mode(saved_mode); - - return nmodes; -} - -__videocard video_bios = -{ - .card_name = "BIOS (scanned)", - .probe = bios_probe, - .set_mode = bios_set_mode, - .unsafe = 1, - .xmode_first = VIDEO_FIRST_BIOS, - .xmode_n = 0x80, -}; diff --git a/trunk/arch/i386/boot/video-vesa.c b/trunk/arch/i386/boot/video-vesa.c deleted file mode 100644 index e6aa9eb8d93a..000000000000 --- a/trunk/arch/i386/boot/video-vesa.c +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/video-vesa.c - * - * VESA text modes - */ - -#include "boot.h" -#include "video.h" -#include "vesa.h" - -/* VESA information */ -static struct vesa_general_info vginfo; -static struct vesa_mode_info vminfo; - -__videocard video_vesa; - -static void vesa_store_mode_params_graphics(void); - -static int vesa_probe(void) -{ -#if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID) - u16 ax; - u16 mode; - addr_t mode_ptr; - struct mode_info *mi; - int nmodes = 0; - - video_vesa.modes = GET_HEAP(struct mode_info, 0); - - vginfo.signature = VBE2_MAGIC; - - /* Optimistically assume a VESA BIOS is register-clean... */ - ax = 0x4f00; - asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo)); - - if (ax != 0x004f || - vginfo.signature != VESA_MAGIC || - vginfo.version < 0x0102) - return 0; /* Not present */ -#endif /* CONFIG_VIDEO_VESA || CONFIG_FIRMWARE_EDID */ -#ifdef CONFIG_VIDEO_VESA - set_fs(vginfo.video_mode_ptr.seg); - mode_ptr = vginfo.video_mode_ptr.off; - - while ((mode = rdfs16(mode_ptr)) != 0xffff) { - mode_ptr += 2; - - if (heap_free() < sizeof(struct mode_info)) - break; /* Heap full, can't save mode info */ - - if (mode & ~0x1ff) - continue; - - memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ - - ax = 0x4f01; - asm("int $0x10" - : "+a" (ax), "=m" (vminfo) - : "c" (mode), "D" (&vminfo)); - - if (ax != 0x004f) - continue; - - if ((vminfo.mode_attr & 0x15) == 0x05) { - /* Text Mode, TTY BIOS supported, - supported by hardware */ - mi = GET_HEAP(struct mode_info, 1); - mi->mode = mode + VIDEO_FIRST_VESA; - mi->x = vminfo.h_res; - mi->y = vminfo.v_res; - nmodes++; - } else if ((vminfo.mode_attr & 0x99) == 0x99) { -#ifdef CONFIG_FB - /* Graphics mode, color, linear frame buffer - supported -- register the mode but hide from - the menu. Only do this if framebuffer is - configured, however, otherwise the user will - be left without a screen. */ - mi = GET_HEAP(struct mode_info, 1); - mi->mode = mode + VIDEO_FIRST_VESA; - mi->x = mi->y = 0; - nmodes++; -#endif - } - } - - return nmodes; -#else - return 0; -#endif /* CONFIG_VIDEO_VESA */ -} - -static int vesa_set_mode(struct mode_info *mode) -{ - u16 ax; - int is_graphic; - u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; - - memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ - - ax = 0x4f01; - asm("int $0x10" - : "+a" (ax), "=m" (vminfo) - : "c" (vesa_mode), "D" (&vminfo)); - - if (ax != 0x004f) - return -1; - - if ((vminfo.mode_attr & 0x15) == 0x05) { - /* It's a supported text mode */ - is_graphic = 0; - } else if ((vminfo.mode_attr & 0x99) == 0x99) { - /* It's a graphics mode with linear frame buffer */ - is_graphic = 1; - vesa_mode |= 0x4000; /* Request linear frame buffer */ - } else { - return -1; /* Invalid mode */ - } - - - ax = 0x4f02; - asm volatile("int $0x10" - : "+a" (ax) - : "b" (vesa_mode), "D" (0)); - - if (ax != 0x004f) - return -1; - - graphic_mode = is_graphic; - if (!is_graphic) { - /* Text mode */ - force_x = mode->x; - force_y = mode->y; - do_restore = 1; - } else { - /* Graphics mode */ - vesa_store_mode_params_graphics(); - } - - return 0; -} - - -/* Switch DAC to 8-bit mode */ -static void vesa_dac_set_8bits(void) -{ - u8 dac_size = 6; - - /* If possible, switch the DAC to 8-bit mode */ - if (vginfo.capabilities & 1) { - u16 ax, bx; - - ax = 0x4f08; - bx = 0x0800; - asm volatile(INT10 - : "+a" (ax), "+b" (bx) - : : "ecx", "edx", "esi", "edi"); - - if (ax == 0x004f) - dac_size = bx >> 8; - } - - /* Set the color sizes to the DAC size, and offsets to 0 */ - boot_params.screen_info.red_size = dac_size; - boot_params.screen_info.green_size = dac_size; - boot_params.screen_info.blue_size = dac_size; - boot_params.screen_info.rsvd_size = dac_size; - - boot_params.screen_info.red_pos = 0; - boot_params.screen_info.green_pos = 0; - boot_params.screen_info.blue_pos = 0; - boot_params.screen_info.rsvd_pos = 0; -} - -/* Save the VESA protected mode info */ -static void vesa_store_pm_info(void) -{ - u16 ax, bx, di, es; - - ax = 0x4f0a; - bx = di = 0; - asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es" - : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di) - : : "ecx", "esi"); - - if (ax != 0x004f) - return; - - boot_params.screen_info.vesapm_seg = es; - boot_params.screen_info.vesapm_off = di; -} - -/* - * Save video mode parameters for graphics mode - */ -static void vesa_store_mode_params_graphics(void) -{ - /* Tell the kernel we're in VESA graphics mode */ - boot_params.screen_info.orig_video_isVGA = 0x23; - - /* Mode parameters */ - boot_params.screen_info.vesa_attributes = vminfo.mode_attr; - boot_params.screen_info.lfb_linelength = vminfo.logical_scan; - boot_params.screen_info.lfb_width = vminfo.h_res; - boot_params.screen_info.lfb_height = vminfo.v_res; - boot_params.screen_info.lfb_depth = vminfo.bpp; - boot_params.screen_info.pages = vminfo.image_planes; - boot_params.screen_info.lfb_base = vminfo.lfb_ptr; - memcpy(&boot_params.screen_info.red_size, - &vminfo.rmask, 8); - - /* General parameters */ - boot_params.screen_info.lfb_size = vginfo.total_memory; - - if (vminfo.bpp <= 8) - vesa_dac_set_8bits(); - - vesa_store_pm_info(); -} - -/* - * Save EDID information for the kernel; this is invoked, separately, - * after mode-setting. - */ -void vesa_store_edid(void) -{ -#ifdef CONFIG_FIRMWARE_EDID - u16 ax, bx, cx, dx, di; - - /* Apparently used as a nonsense token... */ - memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info); - - if (vginfo.version < 0x0200) - return; /* EDID requires VBE 2.0+ */ - - ax = 0x4f15; /* VBE DDC */ - bx = 0x0000; /* Report DDC capabilities */ - cx = 0; /* Controller 0 */ - di = 0; /* ES:DI must be 0 by spec */ - - /* Note: The VBE DDC spec is different from the main VESA spec; - we genuinely have to assume all registers are destroyed here. */ - - asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" - : "+a" (ax), "+b" (bx) - : "c" (cx), "D" (di) - : "esi"); - - if (ax != 0x004f) - return; /* No EDID */ - - /* BH = time in seconds to transfer EDD information */ - /* BL = DDC level supported */ - - ax = 0x4f15; /* VBE DDC */ - bx = 0x0001; /* Read EDID */ - cx = 0; /* Controller 0 */ - dx = 0; /* EDID block number */ - di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ - asm(INT10 - : "+a" (ax), "+b" (bx), "+d" (dx) - : "c" (cx), "D" (di) - : "esi"); -#endif /* CONFIG_FIRMWARE_EDID */ -} - -__videocard video_vesa = -{ - .card_name = "VESA", - .probe = vesa_probe, - .set_mode = vesa_set_mode, - .xmode_first = VIDEO_FIRST_VESA, - .xmode_n = 0x200, -}; diff --git a/trunk/arch/i386/boot/video-vga.c b/trunk/arch/i386/boot/video-vga.c deleted file mode 100644 index 700d09a9c9b3..000000000000 --- a/trunk/arch/i386/boot/video-vga.c +++ /dev/null @@ -1,260 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/video-vga.c - * - * Common all-VGA modes - */ - -#include "boot.h" -#include "video.h" - -static struct mode_info vga_modes[] = { - { VIDEO_80x25, 80, 25 }, - { VIDEO_8POINT, 80, 50 }, - { VIDEO_80x43, 80, 43 }, - { VIDEO_80x28, 80, 28 }, - { VIDEO_80x30, 80, 30 }, - { VIDEO_80x34, 80, 34 }, - { VIDEO_80x60, 80, 60 }, -}; - -static struct mode_info ega_modes[] = { - { VIDEO_80x25, 80, 25 }, - { VIDEO_8POINT, 80, 43 }, -}; - -static struct mode_info cga_modes[] = { - { VIDEO_80x25, 80, 25 }, -}; - -__videocard video_vga; - -/* Set basic 80x25 mode */ -static u8 vga_set_basic_mode(void) -{ - u16 ax; - u8 rows; - u8 mode; - -#ifdef CONFIG_VIDEO_400_HACK - if (adapter >= ADAPTER_VGA) { - asm(INT10 - : : "a" (0x1202), "b" (0x0030) - : "ecx", "edx", "esi", "edi"); - } -#endif - - ax = 0x0f00; - asm(INT10 - : "+a" (ax) - : : "ebx", "ecx", "edx", "esi", "edi"); - - mode = (u8)ax; - - set_fs(0); - rows = rdfs8(0x484); /* rows minus one */ - -#ifndef CONFIG_VIDEO_400_HACK - if ((ax == 0x5003 || ax == 0x5007) && - (rows == 0 || rows == 24)) - return mode; -#endif - - if (mode != 3 && mode != 7) - mode = 3; - - /* Set the mode */ - asm volatile(INT10 - : : "a" (mode) - : "ebx", "ecx", "edx", "esi", "edi"); - do_restore = 1; - return mode; -} - -static void vga_set_8font(void) -{ - /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */ - - /* Set 8x8 font */ - asm volatile(INT10 : : "a" (0x1112), "b" (0)); - - /* Use alternate print screen */ - asm volatile(INT10 : : "a" (0x1200), "b" (0x20)); - - /* Turn off cursor emulation */ - asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); - - /* Cursor is scan lines 6-7 */ - asm volatile(INT10 : : "a" (0x0100), "c" (0x0607)); -} - -static void vga_set_14font(void) -{ - /* Set 9x14 font - 80x28 on VGA */ - - /* Set 9x14 font */ - asm volatile(INT10 : : "a" (0x1111), "b" (0)); - - /* Turn off cursor emulation */ - asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); - - /* Cursor is scan lines 11-12 */ - asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c)); -} - -static void vga_set_80x43(void) -{ - /* Set 80x43 mode on VGA (not EGA) */ - - /* Set 350 scans */ - asm volatile(INT10 : : "a" (0x1201), "b" (0x30)); - - /* Reset video mode */ - asm volatile(INT10 : : "a" (0x0003)); - - vga_set_8font(); -} - -/* I/O address of the VGA CRTC */ -u16 vga_crtc(void) -{ - return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4; -} - -static void vga_set_480_scanlines(int end) -{ - u16 crtc; - u8 csel; - - crtc = vga_crtc(); - - out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */ - out_idx(0x0b, crtc, 0x06); /* Vertical total */ - out_idx(0x3e, crtc, 0x07); /* Vertical overflow */ - out_idx(0xea, crtc, 0x10); /* Vertical sync start */ - out_idx(end, crtc, 0x12); /* Vertical display end */ - out_idx(0xe7, crtc, 0x15); /* Vertical blank start */ - out_idx(0x04, crtc, 0x16); /* Vertical blank end */ - csel = inb(0x3cc); - csel &= 0x0d; - csel |= 0xe2; - outb(csel, 0x3cc); -} - -static void vga_set_80x30(void) -{ - vga_set_480_scanlines(0xdf); -} - -static void vga_set_80x34(void) -{ - vga_set_14font(); - vga_set_480_scanlines(0xdb); -} - -static void vga_set_80x60(void) -{ - vga_set_8font(); - vga_set_480_scanlines(0xdf); -} - -static int vga_set_mode(struct mode_info *mode) -{ - /* Set the basic mode */ - vga_set_basic_mode(); - - /* Override a possibly broken BIOS */ - force_x = mode->x; - force_y = mode->y; - - switch (mode->mode) { - case VIDEO_80x25: - break; - case VIDEO_8POINT: - vga_set_8font(); - break; - case VIDEO_80x43: - vga_set_80x43(); - break; - case VIDEO_80x28: - vga_set_14font(); - break; - case VIDEO_80x30: - vga_set_80x30(); - break; - case VIDEO_80x34: - vga_set_80x34(); - break; - case VIDEO_80x60: - vga_set_80x60(); - break; - } - - return 0; -} - -/* - * Note: this probe includes basic information required by all - * systems. It should be executed first, by making sure - * video-vga.c is listed first in the Makefile. - */ -static int vga_probe(void) -{ - static const char *card_name[] = { - "CGA/MDA/HGC", "EGA", "VGA" - }; - static struct mode_info *mode_lists[] = { - cga_modes, - ega_modes, - vga_modes, - }; - static int mode_count[] = { - sizeof(cga_modes)/sizeof(struct mode_info), - sizeof(ega_modes)/sizeof(struct mode_info), - sizeof(vga_modes)/sizeof(struct mode_info), - }; - u8 vga_flag; - - asm(INT10 - : "=b" (boot_params.screen_info.orig_video_ega_bx) - : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ - : "ecx", "edx", "esi", "edi"); - - /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ - if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) { - /* EGA/VGA */ - asm(INT10 - : "=a" (vga_flag) - : "a" (0x1a00) - : "ebx", "ecx", "edx", "esi", "edi"); - - if (vga_flag == 0x1a) { - adapter = ADAPTER_VGA; - boot_params.screen_info.orig_video_isVGA = 1; - } else { - adapter = ADAPTER_EGA; - } - } else { - adapter = ADAPTER_CGA; - } - - video_vga.modes = mode_lists[adapter]; - video_vga.card_name = card_name[adapter]; - return mode_count[adapter]; -} - -__videocard video_vga = -{ - .card_name = "VGA", - .probe = vga_probe, - .set_mode = vga_set_mode, -}; diff --git a/trunk/arch/i386/boot/video.S b/trunk/arch/i386/boot/video.S new file mode 100644 index 000000000000..8143c9516cb4 --- /dev/null +++ b/trunk/arch/i386/boot/video.S @@ -0,0 +1,2043 @@ +/* video.S + * + * Display adapter & video mode setup, version 2.13 (14-May-99) + * + * Copyright (C) 1995 -- 1998 Martin Mares + * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson + * + * Rewritten to use GNU 'as' by Chris Noe May 1999 + * + * For further information, look at Documentation/svga.txt. + * + */ + +/* Enable autodetection of SVGA adapters and modes. */ +#undef CONFIG_VIDEO_SVGA + +/* Enable autodetection of VESA modes */ +#define CONFIG_VIDEO_VESA + +/* Enable compacting of mode table */ +#define CONFIG_VIDEO_COMPACT + +/* Retain screen contents when switching modes */ +#define CONFIG_VIDEO_RETAIN + +/* Enable local mode list */ +#undef CONFIG_VIDEO_LOCAL + +/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ +#undef CONFIG_VIDEO_400_HACK + +/* Hack that lets you force specific BIOS mode ID and specific dimensions */ +#undef CONFIG_VIDEO_GFX_HACK +#define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */ +#define VIDEO_GFX_BIOS_BX 0x0102 +#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */ + +/* This code uses an extended set of video mode numbers. These include: + * Aliases for standard modes + * NORMAL_VGA (-1) + * EXTENDED_VGA (-2) + * ASK_VGA (-3) + * Video modes numbered by menu position -- NOT RECOMMENDED because of lack + * of compatibility when extending the table. These are between 0x00 and 0xff. + */ +#define VIDEO_FIRST_MENU 0x0000 + +/* Standard BIOS video modes (BIOS number + 0x0100) */ +#define VIDEO_FIRST_BIOS 0x0100 + +/* VESA BIOS video modes (VESA number + 0x0200) */ +#define VIDEO_FIRST_VESA 0x0200 + +/* Video7 special modes (BIOS number + 0x0900) */ +#define VIDEO_FIRST_V7 0x0900 + +/* Special video modes */ +#define VIDEO_FIRST_SPECIAL 0x0f00 +#define VIDEO_80x25 0x0f00 +#define VIDEO_8POINT 0x0f01 +#define VIDEO_80x43 0x0f02 +#define VIDEO_80x28 0x0f03 +#define VIDEO_CURRENT_MODE 0x0f04 +#define VIDEO_80x30 0x0f05 +#define VIDEO_80x34 0x0f06 +#define VIDEO_80x60 0x0f07 +#define VIDEO_GFX_HACK 0x0f08 +#define VIDEO_LAST_SPECIAL 0x0f09 + +/* Video modes given by resolution */ +#define VIDEO_FIRST_RESOLUTION 0x1000 + +/* The "recalculate timings" flag */ +#define VIDEO_RECALC 0x8000 + +/* Positions of various video parameters passed to the kernel */ +/* (see also include/linux/tty.h) */ +#define PARAM_CURSOR_POS 0x00 +#define PARAM_VIDEO_PAGE 0x04 +#define PARAM_VIDEO_MODE 0x06 +#define PARAM_VIDEO_COLS 0x07 +#define PARAM_VIDEO_EGA_BX 0x0a +#define PARAM_VIDEO_LINES 0x0e +#define PARAM_HAVE_VGA 0x0f +#define PARAM_FONT_POINTS 0x10 + +#define PARAM_LFB_WIDTH 0x12 +#define PARAM_LFB_HEIGHT 0x14 +#define PARAM_LFB_DEPTH 0x16 +#define PARAM_LFB_BASE 0x18 +#define PARAM_LFB_SIZE 0x1c +#define PARAM_LFB_LINELENGTH 0x24 +#define PARAM_LFB_COLORS 0x26 +#define PARAM_VESAPM_SEG 0x2e +#define PARAM_VESAPM_OFF 0x30 +#define PARAM_LFB_PAGES 0x32 +#define PARAM_VESA_ATTRIB 0x34 +#define PARAM_CAPABILITIES 0x36 + +/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ +#ifdef CONFIG_VIDEO_RETAIN +#define DO_STORE call store_screen +#else +#define DO_STORE +#endif /* CONFIG_VIDEO_RETAIN */ + +# This is the main entry point called by setup.S +# %ds *must* be pointing to the bootsector +video: pushw %ds # We use different segments + pushw %ds # FS contains original DS + popw %fs + pushw %cs # DS is equal to CS + popw %ds + pushw %cs # ES is equal to CS + popw %es + xorw %ax, %ax + movw %ax, %gs # GS is zero + cld + call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA) +#ifdef CONFIG_VIDEO_SELECT + movw %fs:(0x01fa), %ax # User selected video mode + cmpw $ASK_VGA, %ax # Bring up the menu + jz vid2 + + call mode_set # Set the mode + jc vid1 + + leaw badmdt, %si # Invalid mode ID + call prtstr +vid2: call mode_menu +vid1: +#ifdef CONFIG_VIDEO_RETAIN + call restore_screen # Restore screen contents +#endif /* CONFIG_VIDEO_RETAIN */ + call store_edid +#endif /* CONFIG_VIDEO_SELECT */ + call mode_params # Store mode parameters + popw %ds # Restore original DS + ret + +# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel. +basic_detect: + movb $0, %fs:(PARAM_HAVE_VGA) + movb $0x12, %ah # Check EGA/VGA + movb $0x10, %bl + int $0x10 + movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel + cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card. + je basret + + incb adapter + movw $0x1a00, %ax # Check EGA or VGA? + int $0x10 + cmpb $0x1a, %al # 1a means VGA... + jne basret # anything else is EGA. + + incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA + incb adapter +basret: ret + +# Store the video mode parameters for later usage by the kernel. +# This is done by asking the BIOS except for the rows/columns +# parameters in the default 80x25 mode -- these are set directly, +# because some very obscure BIOSes supply insane values. +mode_params: +#ifdef CONFIG_VIDEO_SELECT + cmpb $0, graphic_mode + jnz mopar_gr +#endif + movb $0x03, %ah # Read cursor position + xorb %bh, %bh + int $0x10 + movw %dx, %fs:(PARAM_CURSOR_POS) + movb $0x0f, %ah # Read page/mode/width + int $0x10 + movw %bx, %fs:(PARAM_VIDEO_PAGE) + movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width + cmpb $0x7, %al # MDA/HGA => segment differs + jnz mopar0 + + movw $0xb000, video_segment +mopar0: movw %gs:(0x485), %ax # Font size + movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA) + movw force_size, %ax # Forced size? + orw %ax, %ax + jz mopar1 + + movb %ah, %fs:(PARAM_VIDEO_COLS) + movb %al, %fs:(PARAM_VIDEO_LINES) + ret + +mopar1: movb $25, %al + cmpb $0, adapter # If we are on CGA/MDA/HGA, the + jz mopar2 # screen must have 25 lines. + + movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS + incb %al # location of max lines. +mopar2: movb %al, %fs:(PARAM_VIDEO_LINES) + ret + +#ifdef CONFIG_VIDEO_SELECT +# Fetching of VESA frame buffer parameters +mopar_gr: + leaw modelist+1024, %di + movb $0x23, %fs:(PARAM_HAVE_VGA) + movw 16(%di), %ax + movw %ax, %fs:(PARAM_LFB_LINELENGTH) + movw 18(%di), %ax + movw %ax, %fs:(PARAM_LFB_WIDTH) + movw 20(%di), %ax + movw %ax, %fs:(PARAM_LFB_HEIGHT) + movb 25(%di), %al + movb $0, %ah + movw %ax, %fs:(PARAM_LFB_DEPTH) + movb 29(%di), %al + movb $0, %ah + movw %ax, %fs:(PARAM_LFB_PAGES) + movl 40(%di), %eax + movl %eax, %fs:(PARAM_LFB_BASE) + movl 31(%di), %eax + movl %eax, %fs:(PARAM_LFB_COLORS) + movl 35(%di), %eax + movl %eax, %fs:(PARAM_LFB_COLORS+4) + movw 0(%di), %ax + movw %ax, %fs:(PARAM_VESA_ATTRIB) + +# get video mem size + leaw modelist+1024, %di + movw $0x4f00, %ax + int $0x10 + xorl %eax, %eax + movw 18(%di), %ax + movl %eax, %fs:(PARAM_LFB_SIZE) + +# store mode capabilities + movl 10(%di), %eax + movl %eax, %fs:(PARAM_CAPABILITIES) + +# switching the DAC to 8-bit is for <= 8 bpp only + movw %fs:(PARAM_LFB_DEPTH), %ax + cmpw $8, %ax + jg dac_done + +# get DAC switching capability + xorl %eax, %eax + movb 10(%di), %al + testb $1, %al + jz dac_set + +# attempt to switch DAC to 8-bit + movw $0x4f08, %ax + movw $0x0800, %bx + int $0x10 + cmpw $0x004f, %ax + jne dac_set + movb %bh, dac_size # store actual DAC size + +dac_set: +# set color size to DAC size + movb dac_size, %al + movb %al, %fs:(PARAM_LFB_COLORS+0) + movb %al, %fs:(PARAM_LFB_COLORS+2) + movb %al, %fs:(PARAM_LFB_COLORS+4) + movb %al, %fs:(PARAM_LFB_COLORS+6) + +# set color offsets to 0 + movb $0, %fs:(PARAM_LFB_COLORS+1) + movb $0, %fs:(PARAM_LFB_COLORS+3) + movb $0, %fs:(PARAM_LFB_COLORS+5) + movb $0, %fs:(PARAM_LFB_COLORS+7) + +dac_done: +# get protected mode interface informations + movw $0x4f0a, %ax + xorw %bx, %bx + xorw %di, %di + int $0x10 + cmp $0x004f, %ax + jnz no_pm + + movw %es, %fs:(PARAM_VESAPM_SEG) + movw %di, %fs:(PARAM_VESAPM_OFF) +no_pm: ret + +# The video mode menu +mode_menu: + leaw keymsg, %si # "Return/Space/Timeout" message + call prtstr + call flush +nokey: call getkt + + cmpb $0x0d, %al # ENTER ? + je listm # yes - manual mode selection + + cmpb $0x20, %al # SPACE ? + je defmd1 # no - repeat + + call beep + jmp nokey + +defmd1: ret # No mode chosen? Default 80x25 + +listm: call mode_table # List mode table +listm0: leaw name_bann, %si # Print adapter name + call prtstr + movw card_name, %si + orw %si, %si + jnz an2 + + movb adapter, %al + leaw old_name, %si + orb %al, %al + jz an1 + + leaw ega_name, %si + decb %al + jz an1 + + leaw vga_name, %si + jmp an1 + +an2: call prtstr + leaw svga_name, %si +an1: call prtstr + leaw listhdr, %si # Table header + call prtstr + movb $0x30, %dl # DL holds mode number + leaw modelist, %si +lm1: cmpw $ASK_VGA, (%si) # End? + jz lm2 + + movb %dl, %al # Menu selection number + call prtchr + call prtsp2 + lodsw + call prthw # Mode ID + call prtsp2 + movb 0x1(%si), %al + call prtdec # Rows + movb $0x78, %al # the letter 'x' + call prtchr + lodsw + call prtdec # Columns + movb $0x0d, %al # New line + call prtchr + movb $0x0a, %al + call prtchr + incb %dl # Next character + cmpb $0x3a, %dl + jnz lm1 + + movb $0x61, %dl + jmp lm1 + +lm2: leaw prompt, %si # Mode prompt + call prtstr + leaw edit_buf, %di # Editor buffer +lm3: call getkey + cmpb $0x0d, %al # Enter? + jz lment + + cmpb $0x08, %al # Backspace? + jz lmbs + + cmpb $0x20, %al # Printable? + jc lm3 + + cmpw $edit_buf+4, %di # Enough space? + jz lm3 + + stosb + call prtchr + jmp lm3 + +lmbs: cmpw $edit_buf, %di # Backspace + jz lm3 + + decw %di + movb $0x08, %al + call prtchr + call prtspc + movb $0x08, %al + call prtchr + jmp lm3 + +lment: movb $0, (%di) + leaw crlft, %si + call prtstr + leaw edit_buf, %si + cmpb $0, (%si) # Empty string = default mode + jz lmdef + + cmpb $0, 1(%si) # One character = menu selection + jz mnusel + + cmpw $0x6373, (%si) # "scan" => mode scanning + jnz lmhx + + cmpw $0x6e61, 2(%si) + jz lmscan + +lmhx: xorw %bx, %bx # Else => mode ID in hex +lmhex: lodsb + orb %al, %al + jz lmuse1 + + subb $0x30, %al + jc lmbad + + cmpb $10, %al + jc lmhx1 + + subb $7, %al + andb $0xdf, %al + cmpb $10, %al + jc lmbad + + cmpb $16, %al + jnc lmbad + +lmhx1: shlw $4, %bx + orb %al, %bl + jmp lmhex + +lmuse1: movw %bx, %ax + jmp lmuse + +mnusel: lodsb # Menu selection + xorb %ah, %ah + subb $0x30, %al + jc lmbad + + cmpb $10, %al + jc lmuse + + cmpb $0x61-0x30, %al + jc lmbad + + subb $0x61-0x30-10, %al + cmpb $36, %al + jnc lmbad + +lmuse: call mode_set + jc lmdef + +lmbad: leaw unknt, %si + call prtstr + jmp lm2 +lmscan: cmpb $0, adapter # Scanning only on EGA/VGA + jz lmbad + + movw $0, mt_end # Scanning of modes is + movb $1, scanning # done as new autodetection. + call mode_table + jmp listm0 +lmdef: ret + +# Additional parts of mode_set... (relative jumps, you know) +setv7: # Video7 extended modes + DO_STORE + subb $VIDEO_FIRST_V7>>8, %bh + movw $0x6f05, %ax + int $0x10 + stc + ret + +_setrec: jmp setrec # Ugly... +_set_80x25: jmp set_80x25 + +# Aliases for backward compatibility. +setalias: + movw $VIDEO_80x25, %ax + incw %bx + jz mode_set + + movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al + incw %bx + jnz setbad # Fall-through! + +# Setting of user mode (AX=mode ID) => CF=success +mode_set: + movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S + movw %ax, %bx + cmpb $0xff, %ah + jz setalias + + testb $VIDEO_RECALC>>8, %ah + jnz _setrec + + cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah + jnc setres + + cmpb $VIDEO_FIRST_SPECIAL>>8, %ah + jz setspc + + cmpb $VIDEO_FIRST_V7>>8, %ah + jz setv7 + + cmpb $VIDEO_FIRST_VESA>>8, %ah + jnc check_vesa + + orb %ah, %ah + jz setmenu + + decb %ah + jz setbios + +setbad: clc + movb $0, do_restore # The screen needn't be restored + ret + +setvesa: + DO_STORE + subb $VIDEO_FIRST_VESA>>8, %bh + movw $0x4f02, %ax # VESA BIOS mode set call + int $0x10 + cmpw $0x004f, %ax # AL=4f if implemented + jnz setbad # AH=0 if OK + + stc + ret + +setbios: + DO_STORE + int $0x10 # Standard BIOS mode set call + pushw %bx + movb $0x0f, %ah # Check if really set + int $0x10 + popw %bx + cmpb %bl, %al + jnz setbad + + stc + ret + +setspc: xorb %bh, %bh # Set special mode + cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl + jnc setbad + + addw %bx, %bx + jmp *spec_inits(%bx) + +setmenu: + orb %al, %al # 80x25 is an exception + jz _set_80x25 + + pushw %bx # Set mode chosen from menu + call mode_table # Build the mode table + popw %ax + shlw $2, %ax + addw %ax, %si + cmpw %di, %si + jnc setbad + + movw (%si), %ax # Fetch mode ID +_m_s: jmp mode_set + +setres: pushw %bx # Set mode chosen by resolution + call mode_table + popw %bx + xchgb %bl, %bh +setr1: lodsw + cmpw $ASK_VGA, %ax # End of the list? + jz setbad + + lodsw + cmpw %bx, %ax + jnz setr1 + + movw -4(%si), %ax # Fetch mode ID + jmp _m_s + +check_vesa: +#ifdef CONFIG_FIRMWARE_EDID + leaw modelist+1024, %di + movw $0x4f00, %ax + int $0x10 + cmpw $0x004f, %ax + jnz setbad + + movw 4(%di), %ax + movw %ax, vbe_version +#endif + leaw modelist+1024, %di + subb $VIDEO_FIRST_VESA>>8, %bh + movw %bx, %cx # Get mode information structure + movw $0x4f01, %ax + int $0x10 + addb $VIDEO_FIRST_VESA>>8, %bh + cmpw $0x004f, %ax + jnz setbad + + movb (%di), %al # Check capabilities. + andb $0x19, %al + cmpb $0x09, %al + jz setvesa # This is a text mode + + movb (%di), %al # Check capabilities. + andb $0x99, %al + cmpb $0x99, %al + jnz _setbad # Doh! No linear frame buffer. + + subb $VIDEO_FIRST_VESA>>8, %bh + orw $0x4000, %bx # Use linear frame buffer + movw $0x4f02, %ax # VESA BIOS mode set call + int $0x10 + cmpw $0x004f, %ax # AL=4f if implemented + jnz _setbad # AH=0 if OK + + movb $1, graphic_mode # flag graphic mode + movb $0, do_restore # no screen restore + stc + ret + +_setbad: jmp setbad # Ugly... + +# Recalculate vertical display end registers -- this fixes various +# inconsistencies of extended modes on many adapters. Called when +# the VIDEO_RECALC flag is set in the mode ID. + +setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode + call mode_set + jnc rct3 + + movw %gs:(0x485), %ax # Font size in pixels + movb %gs:(0x484), %bl # Number of rows + incb %bl + mulb %bl # Number of visible + decw %ax # scan lines - 1 + movw $0x3d4, %dx + movw %ax, %bx + movb $0x12, %al # Lower 8 bits + movb %bl, %ah + outw %ax, %dx + movb $0x07, %al # Bits 8 and 9 in the overflow register + call inidx + xchgb %al, %ah + andb $0xbd, %ah + shrb %bh + jnc rct1 + orb $0x02, %ah +rct1: shrb %bh + jnc rct2 + orb $0x40, %ah +rct2: movb $0x07, %al + outw %ax, %dx + stc +rct3: ret + +# Table of routines for setting of the special modes. +spec_inits: + .word set_80x25 + .word set_8pixel + .word set_80x43 + .word set_80x28 + .word set_current + .word set_80x30 + .word set_80x34 + .word set_80x60 + .word set_gfx + +# Set the 80x25 mode. If already set, do nothing. +set_80x25: + movw $0x5019, force_size # Override possibly broken BIOS +use_80x25: +#ifdef CONFIG_VIDEO_400_HACK + movw $0x1202, %ax # Force 400 scan lines + movb $0x30, %bl + int $0x10 +#else + movb $0x0f, %ah # Get current mode ID + int $0x10 + cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available + jz st80 # on CGA/MDA/HGA and is also available on EGAM + + cmpw $0x5003, %ax # Unknown mode, force 80x25 color + jnz force3 + +st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25 + jz set80 + + movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc. + orb %al, %al # Some buggy BIOS'es set 0 rows + jz set80 + + cmpb $24, %al # It's hopefully correct + jz set80 +#endif /* CONFIG_VIDEO_400_HACK */ +force3: DO_STORE + movw $0x0003, %ax # Forced set + int $0x10 +set80: stc + ret + +# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls. +set_8pixel: + DO_STORE + call use_80x25 # The base is 80x25 +set_8pt: + movw $0x1112, %ax # Use 8x8 font + xorb %bl, %bl + int $0x10 + movw $0x1200, %ax # Use alternate print screen + movb $0x20, %bl + int $0x10 + movw $0x1201, %ax # Turn off cursor emulation + movb $0x34, %bl + int $0x10 + movb $0x01, %ah # Define cursor scan lines 6-7 + movw $0x0607, %cx + int $0x10 +set_current: + stc + ret + +# Set the 80x28 mode. This mode works on all VGA's, because it's a standard +# 80x25 mode with 14-point fonts instead of 16-point. +set_80x28: + DO_STORE + call use_80x25 # The base is 80x25 +set14: movw $0x1111, %ax # Use 9x14 font + xorb %bl, %bl + int $0x10 + movb $0x01, %ah # Define cursor scan lines 11-12 + movw $0x0b0c, %cx + int $0x10 + stc + ret + +# Set the 80x43 mode. This mode is works on all VGA's. +# It's a 350-scanline mode with 8-pixel font. +set_80x43: + DO_STORE + movw $0x1201, %ax # Set 350 scans + movb $0x30, %bl + int $0x10 + movw $0x0003, %ax # Reset video mode + int $0x10 + jmp set_8pt # Use 8-pixel font + +# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font. +set_80x30: + call use_80x25 # Start with real 80x25 + DO_STORE + movw $0x3cc, %dx # Get CRTC port + inb %dx, %al + movb $0xd4, %dl + rorb %al # Mono or color? + jc set48a + + movb $0xb4, %dl +set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7) + call outidx + movw $0x0b06, %ax # Vertical total + call outidx + movw $0x3e07, %ax # (Vertical) overflow + call outidx + movw $0xea10, %ax # Vertical sync start + call outidx + movw $0xdf12, %ax # Vertical display end + call outidx + movw $0xe715, %ax # Vertical blank start + call outidx + movw $0x0416, %ax # Vertical blank end + call outidx + pushw %dx + movb $0xcc, %dl # Misc output register (read) + inb %dx, %al + movb $0xc2, %dl # (write) + andb $0x0d, %al # Preserve clock select bits and color bit + orb $0xe2, %al # Set correct sync polarity + outb %al, %dx + popw %dx + movw $0x501e, force_size + stc # That's all. + ret + +# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font. +set_80x34: + call set_80x30 # Set 480 scans + call set14 # And 14-pt font + movw $0xdb12, %ax # VGA vertical display end + movw $0x5022, force_size +setvde: call outidx + stc + ret + +# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font. +set_80x60: + call set_80x30 # Set 480 scans + call set_8pt # And 8-pt font + movw $0xdf12, %ax # VGA vertical display end + movw $0x503c, force_size + jmp setvde + +# Special hack for ThinkPad graphics +set_gfx: +#ifdef CONFIG_VIDEO_GFX_HACK + movw $VIDEO_GFX_BIOS_AX, %ax + movw $VIDEO_GFX_BIOS_BX, %bx + int $0x10 + movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size + stc +#endif + ret + +#ifdef CONFIG_VIDEO_RETAIN + +# Store screen contents to temporary buffer. +store_screen: + cmpb $0, do_restore # Already stored? + jnz stsr + + testb $CAN_USE_HEAP, loadflags # Have we space for storing? + jz stsr + + pushw %ax + pushw %bx + pushw force_size # Don't force specific size + movw $0, force_size + call mode_params # Obtain params of current mode + popw force_size + movb %fs:(PARAM_VIDEO_LINES), %ah + movb %fs:(PARAM_VIDEO_COLS), %al + movw %ax, %bx # BX=dimensions + mulb %ah + movw %ax, %cx # CX=number of characters + addw %ax, %ax # Calculate image size + addw $modelist+1024+4, %ax + cmpw heap_end_ptr, %ax + jnc sts1 # Unfortunately, out of memory + + movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params + leaw modelist+1024, %di + stosw + movw %bx, %ax + stosw + pushw %ds # Store the screen + movw video_segment, %ds + xorw %si, %si + rep + movsw + popw %ds + incb do_restore # Screen will be restored later +sts1: popw %bx + popw %ax +stsr: ret + +# Restore screen contents from temporary buffer. +restore_screen: + cmpb $0, do_restore # Has the screen been stored? + jz res1 + + call mode_params # Get parameters of current mode + movb %fs:(PARAM_VIDEO_LINES), %cl + movb %fs:(PARAM_VIDEO_COLS), %ch + leaw modelist+1024, %si # Screen buffer + lodsw # Set cursor position + movw %ax, %dx + cmpb %cl, %dh + jc res2 + + movb %cl, %dh + decb %dh +res2: cmpb %ch, %dl + jc res3 + + movb %ch, %dl + decb %dl +res3: movb $0x02, %ah + movb $0x00, %bh + int $0x10 + lodsw # Display size + movb %ah, %dl # DL=number of lines + movb $0, %ah # BX=phys. length of orig. line + movw %ax, %bx + cmpb %cl, %dl # Too many? + jc res4 + + pushw %ax + movb %dl, %al + subb %cl, %al + mulb %bl + addw %ax, %si + addw %ax, %si + popw %ax + movb %cl, %dl +res4: cmpb %ch, %al # Too wide? + jc res5 + + movb %ch, %al # AX=width of src. line +res5: movb $0, %cl + xchgb %ch, %cl + movw %cx, %bp # BP=width of dest. line + pushw %es + movw video_segment, %es + xorw %di, %di # Move the data + addw %bx, %bx # Convert BX and BP to _bytes_ + addw %bp, %bp +res6: pushw %si + pushw %di + movw %ax, %cx + rep + movsw + popw %di + popw %si + addw %bp, %di + addw %bx, %si + decb %dl + jnz res6 + + popw %es # Done +res1: ret +#endif /* CONFIG_VIDEO_RETAIN */ + +# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port) +outidx: outb %al, %dx + pushw %ax + movb %ah, %al + incw %dx + outb %al, %dx + decw %dx + popw %ax + ret + +# Build the table of video modes (stored after the setup.S code at the +# `modelist' label. Each video mode record looks like: +# .word MODE-ID (our special mode ID (see above)) +# .byte rows (number of rows) +# .byte columns (number of columns) +# Returns address of the end of the table in DI, the end is marked +# with a ASK_VGA ID. +mode_table: + movw mt_end, %di # Already filled? + orw %di, %di + jnz mtab1x + + leaw modelist, %di # Store standard modes: + movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL) + stosl + movb adapter, %al # CGA/MDA/HGA -- no more modes + orb %al, %al + jz mtabe + + decb %al + jnz mtabv + + movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode + stosl + jmp mtabe + +mtab1x: jmp mtab1 + +mtabv: leaw vga_modes, %si # All modes for std VGA + movw $vga_modes_end-vga_modes, %cx + rep # I'm unable to use movsw as I don't know how to store a half + movsb # of the expression above to cx without using explicit shr. + + cmpb $0, scanning # Mode scan requested? + jz mscan1 + + call mode_scan +mscan1: + +#ifdef CONFIG_VIDEO_LOCAL + call local_modes +#endif /* CONFIG_VIDEO_LOCAL */ + +#ifdef CONFIG_VIDEO_VESA + call vesa_modes # Detect VESA VGA modes +#endif /* CONFIG_VIDEO_VESA */ + +#ifdef CONFIG_VIDEO_SVGA + cmpb $0, scanning # Bypass when scanning + jnz mscan2 + + call svga_modes # Detect SVGA cards & modes +mscan2: +#endif /* CONFIG_VIDEO_SVGA */ + +mtabe: + +#ifdef CONFIG_VIDEO_COMPACT + leaw modelist, %si + movw %di, %dx + movw %si, %di +cmt1: cmpw %dx, %si # Scan all modes + jz cmt2 + + leaw modelist, %bx # Find in previous entries + movw 2(%si), %cx +cmt3: cmpw %bx, %si + jz cmt4 + + cmpw 2(%bx), %cx # Found => don't copy this entry + jz cmt5 + + addw $4, %bx + jmp cmt3 + +cmt4: movsl # Copy entry + jmp cmt1 + +cmt5: addw $4, %si # Skip entry + jmp cmt1 + +cmt2: +#endif /* CONFIG_VIDEO_COMPACT */ + + movw $ASK_VGA, (%di) # End marker + movw %di, mt_end +mtab1: leaw modelist, %si # SI=mode list, DI=list end +ret0: ret + +# Modes usable on all standard VGAs +vga_modes: + .word VIDEO_8POINT + .word 0x5032 # 80x50 + .word VIDEO_80x43 + .word 0x502b # 80x43 + .word VIDEO_80x28 + .word 0x501c # 80x28 + .word VIDEO_80x30 + .word 0x501e # 80x30 + .word VIDEO_80x34 + .word 0x5022 # 80x34 + .word VIDEO_80x60 + .word 0x503c # 80x60 +#ifdef CONFIG_VIDEO_GFX_HACK + .word VIDEO_GFX_HACK + .word VIDEO_GFX_DUMMY_RESOLUTION +#endif + +vga_modes_end: +# Detect VESA modes. + +#ifdef CONFIG_VIDEO_VESA +vesa_modes: + cmpb $2, adapter # VGA only + jnz ret0 + + movw %di, %bp # BP=original mode table end + addw $0x200, %di # Buffer space + movw $0x4f00, %ax # VESA Get card info call + int $0x10 + movw %bp, %di + cmpw $0x004f, %ax # Successful? + jnz ret0 + + cmpw $0x4556, 0x200(%di) + jnz ret0 + + cmpw $0x4153, 0x202(%di) + jnz ret0 + + movw $vesa_name, card_name # Set name to "VESA VGA" + pushw %gs + lgsw 0x20e(%di), %si # GS:SI=mode list + movw $128, %cx # Iteration limit +vesa1: +# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst. +# XXX: lodsw %gs:(%si), %ax # Get next mode in the list + gs; lodsw + cmpw $0xffff, %ax # End of the table? + jz vesar + + cmpw $0x0080, %ax # Check validity of mode ID + jc vesa2 + + orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff + jz vesan # Certain BIOSes report 0x80-0xff! + + cmpw $0x0800, %ax + jnc vesae + +vesa2: pushw %cx + movw %ax, %cx # Get mode information structure + movw $0x4f01, %ax + int $0x10 + movw %cx, %bx # BX=mode number + addb $VIDEO_FIRST_VESA>>8, %bh + popw %cx + cmpw $0x004f, %ax + jnz vesan # Don't report errors (buggy BIOSES) + + movb (%di), %al # Check capabilities. We require + andb $0x19, %al # a color text mode. + cmpb $0x09, %al + jnz vesan + + cmpw $0xb800, 8(%di) # Standard video memory address required + jnz vesan + + testb $2, (%di) # Mode characteristics supplied? + movw %bx, (%di) # Store mode number + jz vesa3 + + xorw %dx, %dx + movw 0x12(%di), %bx # Width + orb %bh, %bh + jnz vesan + + movb %bl, 0x3(%di) + movw 0x14(%di), %ax # Height + orb %ah, %ah + jnz vesan + + movb %al, 2(%di) + mulb %bl + cmpw $8193, %ax # Small enough for Linux console driver? + jnc vesan + + jmp vesaok + +vesa3: subw $0x8108, %bx # This mode has no detailed info specified, + jc vesan # so it must be a standard VESA mode. + + cmpw $5, %bx + jnc vesan + + movw vesa_text_mode_table(%bx), %ax + movw %ax, 2(%di) +vesaok: addw $4, %di # The mode is valid. Store it. +vesan: loop vesa1 # Next mode. Limit exceeded => error +vesae: leaw vesaer, %si + call prtstr + movw %bp, %di # Discard already found modes. +vesar: popw %gs + ret + +# Dimensions of standard VESA text modes +vesa_text_mode_table: + .byte 60, 80 # 0108 + .byte 25, 132 # 0109 + .byte 43, 132 # 010A + .byte 50, 132 # 010B + .byte 60, 132 # 010C +#endif /* CONFIG_VIDEO_VESA */ + +# Scan for video modes. A bit dirty, but should work. +mode_scan: + movw $0x0100, %cx # Start with mode 0 +scm1: movb $0, %ah # Test the mode + movb %cl, %al + int $0x10 + movb $0x0f, %ah + int $0x10 + cmpb %cl, %al + jnz scm2 # Mode not set + + movw $0x3c0, %dx # Test if it's a text mode + movb $0x10, %al # Mode bits + call inidx + andb $0x03, %al + jnz scm2 + + movb $0xce, %dl # Another set of mode bits + movb $0x06, %al + call inidx + shrb %al + jc scm2 + + movb $0xd4, %dl # Cursor location + movb $0x0f, %al + call inidx + orb %al, %al + jnz scm2 + + movw %cx, %ax # Ok, store the mode + stosw + movb %gs:(0x484), %al # Number of rows + incb %al + stosb + movw %gs:(0x44a), %ax # Number of columns + stosb +scm2: incb %cl + jns scm1 + + movw $0x0003, %ax # Return back to mode 3 + int $0x10 + ret + +tstidx: outw %ax, %dx # OUT DX,AX and inidx +inidx: outb %al, %dx # Read from indexed VGA register + incw %dx # AL=index, DX=index reg port -> AL=data + inb %dx, %al + decw %dx + ret + +# Try to detect type of SVGA card and supply (usually approximate) video +# mode table for it. + +#ifdef CONFIG_VIDEO_SVGA +svga_modes: + leaw svga_table, %si # Test all known SVGA adapters +dosvga: lodsw + movw %ax, %bp # Default mode table + orw %ax, %ax + jz didsv1 + + lodsw # Pointer to test routine + pushw %si + pushw %di + pushw %es + movw $0xc000, %bx + movw %bx, %es + call *%ax # Call test routine + popw %es + popw %di + popw %si + orw %bp, %bp + jz dosvga + + movw %bp, %si # Found, copy the modes + movb svga_prefix, %ah +cpsvga: lodsb + orb %al, %al + jz didsv + + stosw + movsw + jmp cpsvga + +didsv: movw %si, card_name # Store pointer to card name +didsv1: ret + +# Table of all known SVGA cards. For each card, we store a pointer to +# a table of video modes supported by the card and a pointer to a routine +# used for testing of presence of the card. The video mode table is always +# followed by the name of the card or the chipset. +svga_table: + .word ati_md, ati_test + .word oak_md, oak_test + .word paradise_md, paradise_test + .word realtek_md, realtek_test + .word s3_md, s3_test + .word chips_md, chips_test + .word video7_md, video7_test + .word cirrus5_md, cirrus5_test + .word cirrus6_md, cirrus6_test + .word cirrus1_md, cirrus1_test + .word ahead_md, ahead_test + .word everex_md, everex_test + .word genoa_md, genoa_test + .word trident_md, trident_test + .word tseng_md, tseng_test + .word 0 + +# Test routines and mode tables: + +# S3 - The test algorithm was taken from the SuperProbe package +# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org +s3_test: + movw $0x0f35, %cx # we store some constants in cl/ch + movw $0x03d4, %dx + movb $0x38, %al + call inidx + movb %al, %bh # store current CRT-register 0x38 + movw $0x0038, %ax + call outidx # disable writing to special regs + movb %cl, %al # check whether we can write special reg 0x35 + call inidx + movb %al, %bl # save the current value of CRT reg 0x35 + andb $0xf0, %al # clear bits 0-3 + movb %al, %ah + movb %cl, %al # and write it to CRT reg 0x35 + call outidx + call inidx # now read it back + andb %ch, %al # clear the upper 4 bits + jz s3_2 # the first test failed. But we have a + + movb %bl, %ah # second chance + movb %cl, %al + call outidx + jmp s3_1 # do the other tests + +s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35 + orb %bl, %ah # set the upper 4 bits of ah with the orig value + call outidx # write ... + call inidx # ... and reread + andb %cl, %al # turn off the upper 4 bits + pushw %ax + movb %bl, %ah # restore old value in register 0x35 + movb %cl, %al + call outidx + popw %ax + cmpb %ch, %al # setting lower 4 bits was successful => bad + je no_s3 # writing is allowed => this is not an S3 + +s3_1: movw $0x4838, %ax # allow writing to special regs by putting + call outidx # magic number into CRT-register 0x38 + movb %cl, %al # check whether we can write special reg 0x35 + call inidx + movb %al, %bl + andb $0xf0, %al + movb %al, %ah + movb %cl, %al + call outidx + call inidx + andb %ch, %al + jnz no_s3 # no, we can't write => no S3 + + movw %cx, %ax + orb %bl, %ah + call outidx + call inidx + andb %ch, %al + pushw %ax + movb %bl, %ah # restore old value in register 0x35 + movb %cl, %al + call outidx + popw %ax + cmpb %ch, %al + jne no_s31 # writing not possible => no S3 + movb $0x30, %al + call inidx # now get the S3 id ... + leaw idS3, %di + movw $0x10, %cx + repne + scasb + je no_s31 + + movb %bh, %ah + movb $0x38, %al + jmp s3rest + +no_s3: movb $0x35, %al # restore CRT register 0x35 + movb %bl, %ah + call outidx +no_s31: xorw %bp, %bp # Detection failed +s3rest: movb %bh, %ah + movb $0x38, %al # restore old value of CRT register 0x38 + jmp outidx + +idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 + .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0 + +s3_md: .byte 0x54, 0x2b, 0x84 + .byte 0x55, 0x19, 0x84 + .byte 0 + .ascii "S3" + .byte 0 + +# ATI cards. +ati_test: + leaw idati, %si + movw $0x31, %di + movw $0x09, %cx + repe + cmpsb + je atiok + + xorw %bp, %bp +atiok: ret + +idati: .ascii "761295520" + +ati_md: .byte 0x23, 0x19, 0x84 + .byte 0x33, 0x2c, 0x84 + .byte 0x22, 0x1e, 0x64 + .byte 0x21, 0x19, 0x64 + .byte 0x58, 0x21, 0x50 + .byte 0x5b, 0x1e, 0x50 + .byte 0 + .ascii "ATI" + .byte 0 + +# AHEAD +ahead_test: + movw $0x200f, %ax + movw $0x3ce, %dx + outw %ax, %dx + incw %dx + inb %dx, %al + cmpb $0x20, %al + je isahed + + cmpb $0x21, %al + je isahed + + xorw %bp, %bp +isahed: ret + +ahead_md: + .byte 0x22, 0x2c, 0x84 + .byte 0x23, 0x19, 0x84 + .byte 0x24, 0x1c, 0x84 + .byte 0x2f, 0x32, 0xa0 + .byte 0x32, 0x22, 0x50 + .byte 0x34, 0x42, 0x50 + .byte 0 + .ascii "Ahead" + .byte 0 + +# Chips & Tech. +chips_test: + movw $0x3c3, %dx + inb %dx, %al + orb $0x10, %al + outb %al, %dx + movw $0x104, %dx + inb %dx, %al + movb %al, %bl + movw $0x3c3, %dx + inb %dx, %al + andb $0xef, %al + outb %al, %dx + cmpb $0xa5, %bl + je cantok + + xorw %bp, %bp +cantok: ret + +chips_md: + .byte 0x60, 0x19, 0x84 + .byte 0x61, 0x32, 0x84 + .byte 0 + .ascii "Chips & Technologies" + .byte 0 + +# Cirrus Logic 5X0 +cirrus1_test: + movw $0x3d4, %dx + movb $0x0c, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bl + xorb %al, %al + outb %al, %dx + decw %dx + movb $0x1f, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bh + xorb %ah, %ah + shlb $4, %al + movw %ax, %cx + movb %bh, %al + shrb $4, %al + addw %ax, %cx + shlw $8, %cx + addw $6, %cx + movw %cx, %ax + movw $0x3c4, %dx + outw %ax, %dx + incw %dx + inb %dx, %al + andb %al, %al + jnz nocirr + + movb %bh, %al + outb %al, %dx + inb %dx, %al + cmpb $0x01, %al + je iscirr + +nocirr: xorw %bp, %bp +iscirr: movw $0x3d4, %dx + movb %bl, %al + xorb %ah, %ah + shlw $8, %ax + addw $0x0c, %ax + outw %ax, %dx + ret + +cirrus1_md: + .byte 0x1f, 0x19, 0x84 + .byte 0x20, 0x2c, 0x84 + .byte 0x22, 0x1e, 0x84 + .byte 0x31, 0x25, 0x64 + .byte 0 + .ascii "Cirrus Logic 5X0" + .byte 0 + +# Cirrus Logic 54XX +cirrus5_test: + movw $0x3c4, %dx + movb $6, %al + call inidx + movb %al, %bl # BL=backup + movw $6, %ax + call tstidx + cmpb $0x0f, %al + jne c5fail + + movw $0x1206, %ax + call tstidx + cmpb $0x12, %al + jne c5fail + + movb $0x1e, %al + call inidx + movb %al, %bh + movb %bh, %ah + andb $0xc0, %ah + movb $0x1e, %al + call tstidx + andb $0x3f, %al + jne c5xx + + movb $0x1e, %al + movb %bh, %ah + orb $0x3f, %ah + call tstidx + xorb $0x3f, %al + andb $0x3f, %al +c5xx: pushf + movb $0x1e, %al + movb %bh, %ah + outw %ax, %dx + popf + je c5done + +c5fail: xorw %bp, %bp +c5done: movb $6, %al + movb %bl, %ah + outw %ax, %dx + ret + +cirrus5_md: + .byte 0x14, 0x19, 0x84 + .byte 0x54, 0x2b, 0x84 + .byte 0 + .ascii "Cirrus Logic 54XX" + .byte 0 + +# Cirrus Logic 64XX -- no known extra modes, but must be identified, because +# it's misidentified by the Ahead test. +cirrus6_test: + movw $0x3ce, %dx + movb $0x0a, %al + call inidx + movb %al, %bl # BL=backup + movw $0xce0a, %ax + call tstidx + orb %al, %al + jne c2fail + + movw $0xec0a, %ax + call tstidx + cmpb $0x01, %al + jne c2fail + + movb $0xaa, %al + call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's. + shrb $4, %al + subb $4, %al + jz c6done + + decb %al + jz c6done + + subb $2, %al + jz c6done + + decb %al + jz c6done + +c2fail: xorw %bp, %bp +c6done: movb $0x0a, %al + movb %bl, %ah + outw %ax, %dx + ret + +cirrus6_md: + .byte 0 + .ascii "Cirrus Logic 64XX" + .byte 0 + +# Everex / Trident +everex_test: + movw $0x7000, %ax + xorw %bx, %bx + int $0x10 + cmpb $0x70, %al + jne noevrx + + shrw $4, %dx + cmpw $0x678, %dx + je evtrid + + cmpw $0x236, %dx + jne evrxok + +evtrid: leaw trident_md, %bp +evrxok: ret + +noevrx: xorw %bp, %bp + ret + +everex_md: + .byte 0x03, 0x22, 0x50 + .byte 0x04, 0x3c, 0x50 + .byte 0x07, 0x2b, 0x64 + .byte 0x08, 0x4b, 0x64 + .byte 0x0a, 0x19, 0x84 + .byte 0x0b, 0x2c, 0x84 + .byte 0x16, 0x1e, 0x50 + .byte 0x18, 0x1b, 0x64 + .byte 0x21, 0x40, 0xa0 + .byte 0x40, 0x1e, 0x84 + .byte 0 + .ascii "Everex/Trident" + .byte 0 + +# Genoa. +genoa_test: + leaw idgenoa, %si # Check Genoa 'clues' + xorw %ax, %ax + movb %es:(0x37), %al + movw %ax, %di + movw $0x04, %cx + decw %si + decw %di +l1: incw %si + incw %di + movb (%si), %al + testb %al, %al + jz l2 + + cmpb %es:(%di), %al +l2: loope l1 + orw %cx, %cx + je isgen + + xorw %bp, %bp +isgen: ret + +idgenoa: .byte 0x77, 0x00, 0x99, 0x66 + +genoa_md: + .byte 0x58, 0x20, 0x50 + .byte 0x5a, 0x2a, 0x64 + .byte 0x60, 0x19, 0x84 + .byte 0x61, 0x1d, 0x84 + .byte 0x62, 0x20, 0x84 + .byte 0x63, 0x2c, 0x84 + .byte 0x64, 0x3c, 0x84 + .byte 0x6b, 0x4f, 0x64 + .byte 0x72, 0x3c, 0x50 + .byte 0x74, 0x42, 0x50 + .byte 0x78, 0x4b, 0x64 + .byte 0 + .ascii "Genoa" + .byte 0 + +# OAK +oak_test: + leaw idoakvga, %si + movw $0x08, %di + movw $0x08, %cx + repe + cmpsb + je isoak + + xorw %bp, %bp +isoak: ret + +idoakvga: .ascii "OAK VGA " + +oak_md: .byte 0x4e, 0x3c, 0x50 + .byte 0x4f, 0x3c, 0x84 + .byte 0x50, 0x19, 0x84 + .byte 0x51, 0x2b, 0x84 + .byte 0 + .ascii "OAK" + .byte 0 + +# WD Paradise. +paradise_test: + leaw idparadise, %si + movw $0x7d, %di + movw $0x04, %cx + repe + cmpsb + je ispara + + xorw %bp, %bp +ispara: ret + +idparadise: .ascii "VGA=" + +paradise_md: + .byte 0x41, 0x22, 0x50 + .byte 0x47, 0x1c, 0x84 + .byte 0x55, 0x19, 0x84 + .byte 0x54, 0x2c, 0x84 + .byte 0 + .ascii "Paradise" + .byte 0 + +# Trident. +trident_test: + movw $0x3c4, %dx + movb $0x0e, %al + outb %al, %dx + incw %dx + inb %dx, %al + xchgb %al, %ah + xorb %al, %al + outb %al, %dx + inb %dx, %al + xchgb %ah, %al + movb %al, %bl # Strange thing ... in the book this wasn't + andb $0x02, %bl # necessary but it worked on my card which + jz setb2 # is a trident. Without it the screen goes + # blurred ... + andb $0xfd, %al + jmp clrb2 + +setb2: orb $0x02, %al +clrb2: outb %al, %dx + andb $0x0f, %ah + cmpb $0x02, %ah + je istrid + + xorw %bp, %bp +istrid: ret + +trident_md: + .byte 0x50, 0x1e, 0x50 + .byte 0x51, 0x2b, 0x50 + .byte 0x52, 0x3c, 0x50 + .byte 0x57, 0x19, 0x84 + .byte 0x58, 0x1e, 0x84 + .byte 0x59, 0x2b, 0x84 + .byte 0x5a, 0x3c, 0x84 + .byte 0 + .ascii "Trident" + .byte 0 + +# Tseng. +tseng_test: + movw $0x3cd, %dx + inb %dx, %al # Could things be this simple ! :-) + movb %al, %bl + movb $0x55, %al + outb %al, %dx + inb %dx, %al + movb %al, %ah + movb %bl, %al + outb %al, %dx + cmpb $0x55, %ah + je istsen + +isnot: xorw %bp, %bp +istsen: ret + +tseng_md: + .byte 0x26, 0x3c, 0x50 + .byte 0x2a, 0x28, 0x64 + .byte 0x23, 0x19, 0x84 + .byte 0x24, 0x1c, 0x84 + .byte 0x22, 0x2c, 0x84 + .byte 0x21, 0x3c, 0x84 + .byte 0 + .ascii "Tseng" + .byte 0 + +# Video7. +video7_test: + movw $0x3cc, %dx + inb %dx, %al + movw $0x3b4, %dx + andb $0x01, %al + jz even7 + + movw $0x3d4, %dx +even7: movb $0x0c, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bl + movb $0x55, %al + outb %al, %dx + inb %dx, %al + decw %dx + movb $0x1f, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bh + decw %dx + movb $0x0c, %al + outb %al, %dx + incw %dx + movb %bl, %al + outb %al, %dx + movb $0x55, %al + xorb $0xea, %al + cmpb %bh, %al + jne isnot + + movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching + ret + +video7_md: + .byte 0x40, 0x2b, 0x50 + .byte 0x43, 0x3c, 0x50 + .byte 0x44, 0x3c, 0x64 + .byte 0x41, 0x19, 0x84 + .byte 0x42, 0x2c, 0x84 + .byte 0x45, 0x1c, 0x84 + .byte 0 + .ascii "Video 7" + .byte 0 + +# Realtek VGA +realtek_test: + leaw idrtvga, %si + movw $0x45, %di + movw $0x0b, %cx + repe + cmpsb + je isrt + + xorw %bp, %bp +isrt: ret + +idrtvga: .ascii "REALTEK VGA" + +realtek_md: + .byte 0x1a, 0x3c, 0x50 + .byte 0x1b, 0x19, 0x84 + .byte 0x1c, 0x1e, 0x84 + .byte 0x1d, 0x2b, 0x84 + .byte 0x1e, 0x3c, 0x84 + .byte 0 + .ascii "REALTEK" + .byte 0 + +#endif /* CONFIG_VIDEO_SVGA */ + +# User-defined local mode table (VGA only) +#ifdef CONFIG_VIDEO_LOCAL +local_modes: + leaw local_mode_table, %si +locm1: lodsw + orw %ax, %ax + jz locm2 + + stosw + movsw + jmp locm1 + +locm2: ret + +# This is the table of local video modes which can be supplied manually +# by the user. Each entry consists of mode ID (word) and dimensions +# (byte for column count and another byte for row count). These modes +# are placed before all SVGA and VESA modes and override them if table +# compacting is enabled. The table must end with a zero word followed +# by NUL-terminated video adapter name. +local_mode_table: + .word 0x0100 # Example: 40x25 + .byte 25,40 + .word 0 + .ascii "Local" + .byte 0 +#endif /* CONFIG_VIDEO_LOCAL */ + +# Read a key and return the ASCII code in al, scan code in ah +getkey: xorb %ah, %ah + int $0x16 + ret + +# Read a key with a timeout of 30 seconds. +# The hardware clock is used to get the time. +getkt: call gettime + addb $30, %al # Wait 30 seconds + cmpb $60, %al + jl lminute + + subb $60, %al +lminute: + movb %al, %cl +again: movb $0x01, %ah + int $0x16 + jnz getkey # key pressed, so get it + + call gettime + cmpb %cl, %al + jne again + + movb $0x20, %al # timeout, return `space' + ret + +# Flush the keyboard buffer +flush: movb $0x01, %ah + int $0x16 + jz empty + + xorb %ah, %ah + int $0x16 + jmp flush + +empty: ret + +# Print hexadecimal number. +prthw: pushw %ax + movb %ah, %al + call prthb + popw %ax +prthb: pushw %ax + shrb $4, %al + call prthn + popw %ax + andb $0x0f, %al +prthn: cmpb $0x0a, %al + jc prth1 + + addb $0x07, %al +prth1: addb $0x30, %al + jmp prtchr + +# Print decimal number in al +prtdec: pushw %ax + pushw %cx + xorb %ah, %ah + movb $0x0a, %cl + idivb %cl + cmpb $0x09, %al + jbe lt100 + + call prtdec + jmp skip10 + +lt100: addb $0x30, %al + call prtchr +skip10: movb %ah, %al + addb $0x30, %al + call prtchr + popw %cx + popw %ax + ret + +store_edid: +#ifdef CONFIG_FIRMWARE_EDID + pushw %es # just save all registers + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %di + + pushw %fs + popw %es + + movl $0x13131313, %eax # memset block with 0x13 + movw $32, %cx + movw $0x140, %di + cld + rep + stosl + + cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0 + jl no_edid + + pushw %es # save ES + xorw %di, %di # Report Capability + pushw %di + popw %es # ES:DI must be 0:0 + movw $0x4f15, %ax + xorw %bx, %bx + xorw %cx, %cx + int $0x10 + popw %es # restore ES + + cmpb $0x00, %ah # call successful + jne no_edid + + cmpb $0x4f, %al # function supported + jne no_edid + + movw $0x4f15, %ax # do VBE/DDC + movw $0x01, %bx + movw $0x00, %cx + movw $0x00, %dx + movw $0x140, %di + int $0x10 + +no_edid: + popw %di # restore all registers + popw %dx + popw %cx + popw %bx + popw %ax + popw %es +#endif + ret + +# VIDEO_SELECT-only variables +mt_end: .word 0 # End of video mode table if built +edit_buf: .space 6 # Line editor buffer +card_name: .word 0 # Pointer to adapter name +scanning: .byte 0 # Performing mode scan +do_restore: .byte 0 # Screen contents altered during mode change +svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes +graphic_mode: .byte 0 # Graphic mode with a linear frame buffer +dac_size: .byte 6 # DAC bit depth +vbe_version: .word 0 # VBE bios version + +# Status messages +keymsg: .ascii "Press to see video modes available, " + .ascii " to continue or wait 30 secs" + .byte 0x0d, 0x0a, 0 + +listhdr: .byte 0x0d, 0x0a + .ascii "Mode: COLSxROWS:" + +crlft: .byte 0x0d, 0x0a, 0 + +prompt: .byte 0x0d, 0x0a + .asciz "Enter mode number or `scan': " + +unknt: .asciz "Unknown mode ID. Try again." + +badmdt: .ascii "You passed an undefined mode number." + .byte 0x0d, 0x0a, 0 + +vesaer: .ascii "Error: Scanning of VESA modes failed. Please " + .ascii "report to ." + .byte 0x0d, 0x0a, 0 + +old_name: .asciz "CGA/MDA/HGA" + +ega_name: .asciz "EGA" + +svga_name: .ascii " " + +vga_name: .asciz "VGA" + +vesa_name: .asciz "VESA" + +name_bann: .asciz "Video adapter: " +#endif /* CONFIG_VIDEO_SELECT */ + +# Other variables: +adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA +video_segment: .word 0xb800 # Video memory segment +force_size: .word 0 # Use this size instead of the one in BIOS vars diff --git a/trunk/arch/i386/boot/video.c b/trunk/arch/i386/boot/video.c deleted file mode 100644 index 3bb3573cd6a1..000000000000 --- a/trunk/arch/i386/boot/video.c +++ /dev/null @@ -1,456 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/video.c - * - * Select video mode - */ - -#include "boot.h" -#include "video.h" -#include "vesa.h" - -/* - * Mode list variables - */ -static struct card_info cards[]; /* List of cards to probe for */ - -/* - * Common variables - */ -int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */ -u16 video_segment; -int force_x, force_y; /* Don't query the BIOS for cols/rows */ - -int do_restore = 0; /* Screen contents changed during mode flip */ -int graphic_mode; /* Graphic mode with linear frame buffer */ - -static void store_cursor_position(void) -{ - u16 curpos; - u16 ax, bx; - - ax = 0x0300; - bx = 0; - asm(INT10 - : "=d" (curpos), "+a" (ax), "+b" (bx) - : : "ecx", "esi", "edi"); - - boot_params.screen_info.orig_x = curpos; - boot_params.screen_info.orig_y = curpos >> 8; -} - -static void store_video_mode(void) -{ - u16 ax, page; - - /* N.B.: the saving of the video page here is a bit silly, - since we pretty much assume page 0 everywhere. */ - ax = 0x0f00; - asm(INT10 - : "+a" (ax), "=b" (page) - : : "ecx", "edx", "esi", "edi"); - - /* Not all BIOSes are clean with respect to the top bit */ - boot_params.screen_info.orig_video_mode = ax & 0x7f; - boot_params.screen_info.orig_video_page = page; -} - -/* - * Store the video mode parameters for later usage by the kernel. - * This is done by asking the BIOS except for the rows/columns - * parameters in the default 80x25 mode -- these are set directly, - * because some very obscure BIOSes supply insane values. - */ -static void store_mode_params(void) -{ - u16 font_size; - int x, y; - - /* For graphics mode, it is up to the mode-setting driver - (currently only video-vesa.c) to store the parameters */ - if (graphic_mode) - return; - - store_cursor_position(); - store_video_mode(); - - if (boot_params.screen_info.orig_video_mode == 0x07) { - /* MDA, HGC, or VGA in monochrome mode */ - video_segment = 0xb000; - } else { - /* CGA, EGA, VGA and so forth */ - video_segment = 0xb800; - } - - set_fs(0); - font_size = rdfs16(0x485); /* Font size, BIOS area */ - boot_params.screen_info.orig_video_points = font_size; - - x = rdfs16(0x44a); - y = (adapter == ADAPTER_CGA) ? 25 : rdfs8(0x484)+1; - - if (force_x) - x = force_x; - if (force_y) - y = force_y; - - boot_params.screen_info.orig_video_cols = x; - boot_params.screen_info.orig_video_lines = y; -} - -/* Probe the video drivers and have them generate their mode lists. */ -static void probe_cards(int unsafe) -{ - struct card_info *card; - static u8 probed[2]; - - if (probed[unsafe]) - return; - - probed[unsafe] = 1; - - for (card = video_cards; card < video_cards_end; card++) { - if (card->unsafe == unsafe) { - if (card->probe) - card->nmodes = card->probe(); - else - card->nmodes = 0; - } - } -} - -/* Test if a mode is defined */ -int mode_defined(u16 mode) -{ - struct card_info *card; - struct mode_info *mi; - int i; - - for (card = video_cards; card < video_cards_end; card++) { - mi = card->modes; - for (i = 0; i < card->nmodes; i++, mi++) { - if (mi->mode == mode) - return 1; - } - } - - return 0; -} - -/* Set mode (without recalc) */ -static int raw_set_mode(u16 mode) -{ - int nmode, i; - struct card_info *card; - struct mode_info *mi; - - /* Drop the recalc bit if set */ - mode &= ~VIDEO_RECALC; - - /* Scan for mode based on fixed ID, position, or resolution */ - nmode = 0; - for (card = video_cards; card < video_cards_end; card++) { - mi = card->modes; - for (i = 0; i < card->nmodes; i++, mi++) { - int visible = mi->x || mi->y; - - if ((mode == nmode && visible) || - mode == mi->mode || - mode == (mi->y << 8)+mi->x) - return card->set_mode(mi); - - if (visible) - nmode++; - } - } - - /* Nothing found? Is it an "exceptional" (unprobed) mode? */ - for (card = video_cards; card < video_cards_end; card++) { - if (mode >= card->xmode_first && - mode < card->xmode_first+card->xmode_n) { - struct mode_info mix; - mix.mode = mode; - mix.x = mix.y = 0; - return card->set_mode(&mix); - } - } - - /* Otherwise, failure... */ - return -1; -} - -/* - * Recalculate the vertical video cutoff (hack!) - */ -static void vga_recalc_vertical(void) -{ - unsigned int font_size, rows; - u16 crtc; - u8 ov; - - set_fs(0); - font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ - rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */ - - rows *= font_size; /* Visible scan lines */ - rows--; /* ... minus one */ - - crtc = vga_crtc(); - - out_idx((u8)rows, crtc, 0x12); /* Lower height register */ - ov = in_idx(crtc, 0x07); /* Overflow register */ - ov &= 0xbd; - ov |= (rows >> (8-1)) & 0x02; - ov |= (rows >> (9-6)) & 0x40; - out_idx(ov, crtc, 0x07); -} - -/* Set mode (with recalc if specified) */ -static int set_mode(u16 mode) -{ - int rv; - - /* Very special mode numbers... */ - if (mode == VIDEO_CURRENT_MODE) - return 0; /* Nothing to do... */ - else if (mode == NORMAL_VGA) - mode = VIDEO_80x25; - else if (mode == EXTENDED_VGA) - mode = VIDEO_8POINT; - - rv = raw_set_mode(mode); - if (rv) - return rv; - - if (mode & VIDEO_RECALC) - vga_recalc_vertical(); - - return 0; -} - -static unsigned int get_entry(void) -{ - char entry_buf[4]; - int i, len = 0; - int key; - unsigned int v; - - do { - key = getchar(); - - if (key == '\b') { - if (len > 0) { - puts("\b \b"); - len--; - } - } else if ((key >= '0' && key <= '9') || - (key >= 'A' && key <= 'Z') || - (key >= 'a' && key <= 'z')) { - if (len < sizeof entry_buf) { - entry_buf[len++] = key; - putchar(key); - } - } - } while (key != '\r'); - putchar('\n'); - - if (len == 0) - return VIDEO_CURRENT_MODE; /* Default */ - - v = 0; - for (i = 0; i < len; i++) { - v <<= 4; - key = entry_buf[i] | 0x20; - v += (key > '9') ? key-'a'+10 : key-'0'; - } - - return v; -} - -static void display_menu(void) -{ - struct card_info *card; - struct mode_info *mi; - char ch; - int i; - - puts("Mode: COLSxROWS:\n"); - - ch = '0'; - for (card = video_cards; card < video_cards_end; card++) { - mi = card->modes; - for (i = 0; i < card->nmodes; i++, mi++) { - int visible = mi->x && mi->y; - u16 mode_id = mi->mode ? mi->mode : - (mi->y << 8)+mi->x; - - if (!visible) - continue; /* Hidden mode */ - - printf("%c %04X %3dx%-3d %s\n", - ch, mode_id, mi->x, mi->y, card->card_name); - - if (ch == '9') - ch = 'a'; - else if (ch == 'z' || ch == ' ') - ch = ' '; /* Out of keys... */ - else - ch++; - } - } -} - -#define H(x) ((x)-'a'+10) -#define SCAN ((H('s')<<12)+(H('c')<<8)+(H('a')<<4)+H('n')) - -static unsigned int mode_menu(void) -{ - int key; - unsigned int sel; - - puts("Press to see video modes available, " - " to continue, or wait 30 sec\n"); - - kbd_flush(); - while (1) { - key = getchar_timeout(); - if (key == ' ' || key == 0) - return VIDEO_CURRENT_MODE; /* Default */ - if (key == '\r') - break; - putchar('\a'); /* Beep! */ - } - - - for (;;) { - display_menu(); - - puts("Enter a video mode or \"scan\" to scan for " - "additional modes: "); - sel = get_entry(); - if (sel != SCAN) - return sel; - - probe_cards(1); - } -} - -#ifdef CONFIG_VIDEO_RETAIN -/* Save screen content to the heap */ -struct saved_screen { - int x, y; - int curx, cury; - u16 *data; -} saved; - -static void save_screen(void) -{ - /* Should be called after store_mode_params() */ - saved.x = boot_params.screen_info.orig_video_cols; - saved.y = boot_params.screen_info.orig_video_lines; - saved.curx = boot_params.screen_info.orig_x; - saved.cury = boot_params.screen_info.orig_y; - - if (heap_free() < saved.x*saved.y*sizeof(u16)+512) - return; /* Not enough heap to save the screen */ - - saved.data = GET_HEAP(u16, saved.x*saved.y); - - set_fs(video_segment); - copy_from_fs(saved.data, 0, saved.x*saved.y*sizeof(u16)); -} - -static void restore_screen(void) -{ - /* Should be called after store_mode_params() */ - int xs = boot_params.screen_info.orig_video_cols; - int ys = boot_params.screen_info.orig_video_lines; - int y; - addr_t dst = 0; - u16 *src = saved.data; - u16 ax, bx, dx; - - if (graphic_mode) - return; /* Can't restore onto a graphic mode */ - - if (!src) - return; /* No saved screen contents */ - - /* Restore screen contents */ - - set_fs(video_segment); - for (y = 0; y < ys; y++) { - int npad; - - if (y < saved.y) { - int copy = (xs < saved.x) ? xs : saved.x; - copy_to_fs(dst, src, copy*sizeof(u16)); - dst += copy*sizeof(u16); - src += saved.x; - npad = (xs < saved.x) ? 0 : xs-saved.x; - } else { - npad = xs; - } - - /* Writes "npad" blank characters to - video_segment:dst and advances dst */ - asm volatile("pushw %%es ; " - "movw %2,%%es ; " - "shrw %%cx ; " - "jnc 1f ; " - "stosw \n\t" - "1: rep;stosl ; " - "popw %%es" - : "+D" (dst), "+c" (npad) - : "bdSm" (video_segment), - "a" (0x07200720)); - } - - /* Restore cursor position */ - ax = 0x0200; /* Set cursor position */ - bx = 0; /* Page number (<< 8) */ - dx = (saved.cury << 8)+saved.curx; - asm volatile(INT10 - : "+a" (ax), "+b" (bx), "+d" (dx) - : : "ecx", "esi", "edi"); -} -#else -#define save_screen() ((void)0) -#define restore_screen() ((void)0) -#endif - -void set_video(void) -{ - u16 mode = boot_params.hdr.vid_mode; - - RESET_HEAP(); - - store_mode_params(); - save_screen(); - probe_cards(0); - - for (;;) { - if (mode == ASK_VGA) - mode = mode_menu(); - - if (!set_mode(mode)) - break; - - printf("Undefined video mode number: %x\n", mode); - mode = ASK_VGA; - } - vesa_store_edid(); - store_mode_params(); - - if (do_restore) - restore_screen(); -} diff --git a/trunk/arch/i386/boot/video.h b/trunk/arch/i386/boot/video.h deleted file mode 100644 index 29eca1710b2c..000000000000 --- a/trunk/arch/i386/boot/video.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/video.h - * - * Header file for the real-mode video probing code - */ - -#ifndef BOOT_VIDEO_H -#define BOOT_VIDEO_H - -#include - -/* Enable autodetection of SVGA adapters and modes. */ -#undef CONFIG_VIDEO_SVGA - -/* Enable autodetection of VESA modes */ -#define CONFIG_VIDEO_VESA - -/* Retain screen contents when switching modes */ -#define CONFIG_VIDEO_RETAIN - -/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ -#undef CONFIG_VIDEO_400_HACK - -/* This code uses an extended set of video mode numbers. These include: - * Aliases for standard modes - * NORMAL_VGA (-1) - * EXTENDED_VGA (-2) - * ASK_VGA (-3) - * Video modes numbered by menu position -- NOT RECOMMENDED because of lack - * of compatibility when extending the table. These are between 0x00 and 0xff. - */ -#define VIDEO_FIRST_MENU 0x0000 - -/* Standard BIOS video modes (BIOS number + 0x0100) */ -#define VIDEO_FIRST_BIOS 0x0100 - -/* VESA BIOS video modes (VESA number + 0x0200) */ -#define VIDEO_FIRST_VESA 0x0200 - -/* Video7 special modes (BIOS number + 0x0900) */ -#define VIDEO_FIRST_V7 0x0900 - -/* Special video modes */ -#define VIDEO_FIRST_SPECIAL 0x0f00 -#define VIDEO_80x25 0x0f00 -#define VIDEO_8POINT 0x0f01 -#define VIDEO_80x43 0x0f02 -#define VIDEO_80x28 0x0f03 -#define VIDEO_CURRENT_MODE 0x0f04 -#define VIDEO_80x30 0x0f05 -#define VIDEO_80x34 0x0f06 -#define VIDEO_80x60 0x0f07 -#define VIDEO_GFX_HACK 0x0f08 -#define VIDEO_LAST_SPECIAL 0x0f09 - -/* Video modes given by resolution */ -#define VIDEO_FIRST_RESOLUTION 0x1000 - -/* The "recalculate timings" flag */ -#define VIDEO_RECALC 0x8000 - -/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ -#ifdef CONFIG_VIDEO_RETAIN -void store_screen(void); -#define DO_STORE() store_screen() -#else -#define DO_STORE() ((void)0) -#endif /* CONFIG_VIDEO_RETAIN */ - -/* - * Mode table structures - */ - -struct mode_info { - u16 mode; /* Mode number (vga= style) */ - u8 x, y; /* Width, height */ -}; - -struct card_info { - const char *card_name; - int (*set_mode)(struct mode_info *mode); - int (*probe)(void); - struct mode_info *modes; - int nmodes; /* Number of probed modes so far */ - int unsafe; /* Probing is unsafe, only do after "scan" */ - u16 xmode_first; /* Unprobed modes to try to call anyway */ - u16 xmode_n; /* Size of unprobed mode range */ -}; - -#define __videocard struct card_info __attribute__((section(".videocards"))) -extern struct card_info video_cards[], video_cards_end[]; - -int mode_defined(u16 mode); /* video.c */ - -/* Basic video information */ -#define ADAPTER_CGA 0 /* CGA/MDA/HGC */ -#define ADAPTER_EGA 1 -#define ADAPTER_VGA 2 - -extern int adapter; -extern u16 video_segment; -extern int force_x, force_y; /* Don't query the BIOS for cols/rows */ -extern int do_restore; /* Restore screen contents */ -extern int graphic_mode; /* Graphics mode with linear frame buffer */ - -/* - * int $0x10 is notorious for touching registers it shouldn't. - * gcc doesn't like %ebp being clobbered, so define it as a push/pop - * sequence here. - */ -#define INT10 "pushl %%ebp; int $0x10; popl %%ebp" - -/* Accessing VGA indexed registers */ -static inline u8 in_idx(u16 port, u8 index) -{ - outb(index, port); - return inb(port+1); -} - -static inline void out_idx(u8 v, u16 port, u8 index) -{ - outw(index+(v << 8), port); -} - -/* Writes a value to an indexed port and then reads the port again */ -static inline u8 tst_idx(u8 v, u16 port, u8 index) -{ - out_idx(port, index, v); - return in_idx(port, index); -} - -/* Get the I/O port of the VGA CRTC */ -u16 vga_crtc(void); /* video-vga.c */ - -#endif /* BOOT_VIDEO_H */ diff --git a/trunk/arch/i386/boot/voyager.c b/trunk/arch/i386/boot/voyager.c deleted file mode 100644 index 9221614d0db8..000000000000 --- a/trunk/arch/i386/boot/voyager.c +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- linux-c -*- ------------------------------------------------------- * - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright 2007 rPath, Inc. - All Rights Reserved - * - * This file is part of the Linux kernel, and is made available under - * the terms of the GNU General Public License version 2. - * - * ----------------------------------------------------------------------- */ - -/* - * arch/i386/boot/voyager.c - * - * Get the Voyager config information - */ - -#include "boot.h" - -#ifdef CONFIG_X86_VOYAGER - -int query_voyager(void) -{ - u8 err; - u16 es, di; - /* Abuse the apm_bios_info area for this */ - u8 *data_ptr = (u8 *)&boot_params.apm_bios_info; - - data_ptr[0] = 0xff; /* Flag on config not found(?) */ - - asm("pushw %%es ; " - "int $0x15 ; " - "setc %0 ; " - "movw %%es, %1 ; " - "popw %%es" - : "=qm" (err), "=rm" (es), "=D" (di) - : "a" (0xffc0)); - - if (err) - return -1; /* Not Voyager */ - - set_fs(es); - copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */ - return 0; -} - -#endif /* CONFIG_X86_VOYAGER */ diff --git a/trunk/arch/i386/kernel/cpu/Makefile b/trunk/arch/i386/kernel/cpu/Makefile index 0b6a8551e9e2..74f27a463db0 100644 --- a/trunk/arch/i386/kernel/cpu/Makefile +++ b/trunk/arch/i386/kernel/cpu/Makefile @@ -8,7 +8,7 @@ obj-y += amd.o obj-y += cyrix.o obj-y += centaur.o obj-y += transmeta.o -obj-y += intel.o intel_cacheinfo.o addon_cpuid_features.o +obj-y += intel.o intel_cacheinfo.o obj-y += rise.o obj-y += nexgen.o obj-y += umc.o diff --git a/trunk/arch/i386/kernel/cpu/addon_cpuid_features.c b/trunk/arch/i386/kernel/cpu/addon_cpuid_features.c deleted file mode 100644 index 3e91d3ee26ec..000000000000 --- a/trunk/arch/i386/kernel/cpu/addon_cpuid_features.c +++ /dev/null @@ -1,50 +0,0 @@ - -/* - * Routines to indentify additional cpu features that are scattered in - * cpuid space. - */ - -#include - -#include - -struct cpuid_bit { - u16 feature; - u8 reg; - u8 bit; - u32 level; -}; - -enum cpuid_regs { - CR_EAX = 0, - CR_ECX, - CR_EDX, - CR_EBX -}; - -void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) -{ - u32 max_level; - u32 regs[4]; - const struct cpuid_bit *cb; - - static const struct cpuid_bit cpuid_bits[] = { - { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, - { 0, 0, 0, 0 } - }; - - for (cb = cpuid_bits; cb->feature; cb++) { - - /* Verify that the level is valid */ - max_level = cpuid_eax(cb->level & 0xffff0000); - if (max_level < cb->level || - max_level > (cb->level | 0xffff)) - continue; - - cpuid(cb->level, ®s[CR_EAX], ®s[CR_EBX], - ®s[CR_ECX], ®s[CR_EDX]); - - if (regs[cb->reg] & (1 << cb->bit)) - set_bit(cb->feature, c->x86_capability); - } -} diff --git a/trunk/arch/i386/kernel/cpu/common.c b/trunk/arch/i386/kernel/cpu/common.c index e5419a9dec88..794d593c47eb 100644 --- a/trunk/arch/i386/kernel/cpu/common.c +++ b/trunk/arch/i386/kernel/cpu/common.c @@ -353,8 +353,6 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c) if ( xlvl >= 0x80000004 ) get_model_name(c); /* Default name */ } - - init_scattered_cpuid_features(c); } early_intel_workaround(c); diff --git a/trunk/arch/i386/kernel/cpu/proc.c b/trunk/arch/i386/kernel/cpu/proc.c index 1e31b6caffb1..89d91e6cc972 100644 --- a/trunk/arch/i386/kernel/cpu/proc.c +++ b/trunk/arch/i386/kernel/cpu/proc.c @@ -29,8 +29,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, - NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", - "3dnowext", "3dnow", + NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -41,9 +40,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Other (Linux-defined) */ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, - "constant_tsc", "up", NULL, "arch_perfmon", - "pebs", "bts", NULL, "sync_rdtsc", - "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ @@ -59,16 +57,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* AMD-defined (#2) */ - "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy", - "altmovcr8", "abm", "sse4a", - "misalignsse", "3dnowprefetch", - "osvw", "ibs", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Auxiliary (Linux-defined) */ - "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm", + "sse4a", "misalignsse", + "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/trunk/arch/i386/kernel/e820.c b/trunk/arch/i386/kernel/e820.c index fc822a46897a..9645bb51f76a 100644 --- a/trunk/arch/i386/kernel/e820.c +++ b/trunk/arch/i386/kernel/e820.c @@ -734,7 +734,7 @@ void __init print_memory_map(char *who) case E820_NVS: printk("(ACPI NVS)\n"); break; - default: printk("type %u\n", e820.map[i].type); + default: printk("type %lu\n", e820.map[i].type); break; } } diff --git a/trunk/arch/i386/kernel/setup.c b/trunk/arch/i386/kernel/setup.c index 2d61e65eeb50..698c24fe482e 100644 --- a/trunk/arch/i386/kernel/setup.c +++ b/trunk/arch/i386/kernel/setup.c @@ -102,10 +102,19 @@ static unsigned int highmem_pages = -1; /* * Setup options */ +struct drive_info_struct { char dummy[32]; } drive_info; +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \ + defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) +EXPORT_SYMBOL(drive_info); +#endif struct screen_info screen_info; EXPORT_SYMBOL(screen_info); struct apm_info apm_info; EXPORT_SYMBOL(apm_info); +struct sys_desc_table_struct { + unsigned short length; + unsigned char table[0]; +}; struct edid_info edid_info; EXPORT_SYMBOL_GPL(edid_info); struct ist_info ist_info; @@ -125,7 +134,7 @@ unsigned long saved_videomode; static char __initdata command_line[COMMAND_LINE_SIZE]; -struct boot_params __initdata boot_params; +unsigned char __initdata boot_params[PARAM_SIZE]; #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; @@ -519,6 +528,7 @@ void __init setup_arch(char **cmdline_p) #endif ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); + drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; edid_info = EDID_INFO; apm_info.bios = APM_BIOS_INFO; diff --git a/trunk/arch/i386/kernel/verify_cpu.S b/trunk/arch/i386/kernel/verify_cpu.S new file mode 100644 index 000000000000..f1d1eacf4ab0 --- /dev/null +++ b/trunk/arch/i386/kernel/verify_cpu.S @@ -0,0 +1,94 @@ +/* Check if CPU has some minimum CPUID bits + This runs in 16bit mode so that the caller can still use the BIOS + to output errors on the screen */ +#include +#include + +verify_cpu: + pushfl # Save caller passed flags + pushl $0 # Kill any dangerous flags + popfl + +#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4 + pushfl + pop %eax + orl $(1<<18),%eax # try setting AC + push %eax + popfl + pushfl + popl %eax + testl $(1<<18),%eax + jz bad +#endif +#if REQUIRED_MASK1 != 0 + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx + xorl $0x200000,%eax + pushl %eax + popfl + pushfl + popl %eax + cmpl %eax,%ebx + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx + xorl $0x200000,%eax + pushl %eax + popfl + pushfl + popl %eax + cmpl %eax,%ebx + jz bad # REQUIRED_MASK1 != 0 requires CPUID + + movl $0x0,%eax # See if cpuid 1 is implemented + cpuid + cmpl $0x1,%eax + jb bad # no cpuid 1 + +#if REQUIRED_MASK1 & NEED_CMPXCHG64 + /* Some VIA C3s need magic MSRs to enable CX64. Do this here */ + cmpl $0x746e6543,%ebx # Cent + jne 1f + cmpl $0x48727561,%edx # aurH + jne 1f + cmpl $0x736c7561,%ecx # auls + jne 1f + movl $1,%eax # check model + cpuid + movl %eax,%ebx + shr $8,%ebx + andl $0xf,%ebx + cmp $6,%ebx # check family == 6 + jne 1f + shr $4,%eax + andl $0xf,%eax + cmpl $6,%eax # check model >= 6 + jb 1f + # assume models >= 6 all support this MSR + movl $MSR_VIA_FCR,%ecx + rdmsr + orl $((1<<1)|(1<<7)),%eax # enable CMPXCHG64 and PGE + wrmsr +1: +#endif + movl $0x1,%eax # Does the cpu have what it takes + cpuid + +#if CONFIG_X86_MINIMUM_CPU_MODEL > 4 +#error add proper model checking here +#endif + + andl $REQUIRED_MASK1,%edx + xorl $REQUIRED_MASK1,%edx + jnz bad +#endif /* REQUIRED_MASK1 */ + + popfl + xor %eax,%eax + ret + +bad: + popfl + movl $1,%eax + ret diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index 8bdd25ac1542..5ce94430c019 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -427,10 +427,6 @@ config NR_CPUS This is purely to save memory - each supported CPU requires memory in the static kernel configuration. -config PHYSICAL_ALIGN - hex - default "0x200000" - config HOTPLUG_CPU bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" depends on SMP && HOTPLUG && EXPERIMENTAL diff --git a/trunk/arch/x86_64/boot/Makefile b/trunk/arch/x86_64/boot/Makefile index 67096389de1f..ee6f6505f95f 100644 --- a/trunk/arch/x86_64/boot/Makefile +++ b/trunk/arch/x86_64/boot/Makefile @@ -1,9 +1,135 @@ # # arch/x86_64/boot/Makefile # -# The actual boot code is shared with i386 including the Makefile. -# So tell kbuild that we fetch the code from i386 and include the -# Makefile from i386 too. +# 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. +# +# Copyright (C) 1994 by Linus Torvalds +# + +# ROOT_DEV specifies the default root-device when making the image. +# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case +# the default of FLOPPY is used by 'build'. + +ROOT_DEV := CURRENT + +# If you want to preset the SVGA mode, uncomment the next line and +# set SVGA_MODE to whatever number you want. +# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. +# The number is the same as you would ordinarily press at bootup. + +SVGA_MODE := -DSVGA_MODE=NORMAL_VGA + +# If you want the RAM disk device, define this to be the size in blocks. + +#RAMDISK := -DRAMDISK=512 + +targets := vmlinux.bin bootsect bootsect.o \ + setup setup.o bzImage mtools.conf + +EXTRA_CFLAGS := -m32 + +hostprogs-y := tools/build +HOST_EXTRACFLAGS += $(LINUXINCLUDE) +subdir- := compressed/ #Let make clean descend in compressed/ +# --------------------------------------------------------------------------- + +$(obj)/bzImage: IMAGE_OFFSET := 0x100000 +$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ +$(obj)/bzImage: BUILDFLAGS := -b + +quiet_cmd_image = BUILD $@ +cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ + $(obj)/vmlinux.bin $(ROOT_DEV) > $@ + +$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ + $(obj)/vmlinux.bin $(obj)/tools/build FORCE + $(call if_changed,image) + @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' + +$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE + $(call if_changed,objcopy) + +LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary +LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext + +$(obj)/setup $(obj)/bootsect: %: %.o FORCE + $(call if_changed,ld) + +$(obj)/compressed/vmlinux: FORCE + $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ + +# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel +FDARGS = +# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel +FDINITRD = + +image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,) + +$(obj)/mtools.conf: $(src)/mtools.conf.in + sed -e 's|@OBJ@|$(obj)|g' < $< > $@ + +# This requires write access to /dev/fd0 +zdisk: $(BOOTIMAGE) $(obj)/mtools.conf + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync + syslinux /dev/fd0 ; sync + echo '$(image_cmdline)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg + if [ -f '$(FDINITRD)' ] ; then \ + MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \ + fi + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + +# These require being root or having syslinux 2.02 or higher installed +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync + syslinux $(obj)/fdimage ; sync + echo '$(image_cmdline)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + if [ -f '$(FDINITRD)' ] ; then \ + MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \ + fi + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync + syslinux $(obj)/fdimage ; sync + echo '$(image_cmdline)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + if [ -f '$(FDINITRD)' ] ; then \ + MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \ + fi + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync + +isoimage: $(BOOTIMAGE) + -rm -rf $(obj)/isoimage + mkdir $(obj)/isoimage + for i in lib lib64 share end ; do \ + if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \ + cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \ + break ; \ + fi ; \ + if [ $$i = end ] ; then exit 1 ; fi ; \ + done + cp $(BOOTIMAGE) $(obj)/isoimage/linux + echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg + if [ -f '$(FDINITRD)' ] ; then \ + cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \ + fi + mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + $(obj)/isoimage + rm -rf $(obj)/isoimage + +zlilo: $(BOOTIMAGE) + if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi + if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi + cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz + cp System.map $(INSTALL_PATH)/ + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi -src := arch/i386/boot -include $(src)/Makefile +install: + sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff --git a/trunk/arch/x86_64/boot/bootsect.S b/trunk/arch/x86_64/boot/bootsect.S new file mode 100644 index 000000000000..011b7a4993d4 --- /dev/null +++ b/trunk/arch/x86_64/boot/bootsect.S @@ -0,0 +1,98 @@ +/* + * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds + * + * modified by Drew Eckhardt + * modified by Bruce Evans (bde) + * modified by Chris Noe (May 1999) (as86 -> gas) + * gutted by H. Peter Anvin (Jan 2003) + * + * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment + * addresses must be multiplied by 16 to obtain their respective linear + * addresses. To avoid confusion, linear addresses are written using leading + * hex while segment addresses are written as segment:offset. + * + */ + +#include + +SETUPSECTS = 4 /* default nr of setup-sectors */ +BOOTSEG = 0x07C0 /* original address of boot-sector */ +INITSEG = DEF_INITSEG /* we move boot here - out of the way */ +SETUPSEG = DEF_SETUPSEG /* setup starts here */ +SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ +SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ + /* to be loaded */ +ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ +SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ + +#ifndef SVGA_MODE +#define SVGA_MODE ASK_VGA +#endif + +#ifndef RAMDISK +#define RAMDISK 0 +#endif + +#ifndef ROOT_RDONLY +#define ROOT_RDONLY 1 +#endif + +.code16 +.text + +.global _start +_start: + + # Normalize the start address + jmpl $BOOTSEG, $start2 + +start2: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw $0x7c00, %sp + sti + cld + + movw $bugger_off_msg, %si + +msg_loop: + lodsb + andb %al, %al + jz die + movb $0xe, %ah + movw $7, %bx + int $0x10 + jmp msg_loop + +die: + # Allow the user to press a key, then reboot + xorw %ax, %ax + int $0x16 + int $0x19 + + # int 0x19 should never return. In case it does anyway, + # invoke the BIOS reset code... + ljmp $0xf000,$0xfff0 + + +bugger_off_msg: + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" + .ascii "\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" + .byte 0 + + + # Kernel attributes; used by setup + + .org 497 +setup_sects: .byte SETUPSECTS +root_flags: .word ROOT_RDONLY +syssize: .word SYSSIZE +swap_dev: .word SWAP_DEV +ram_size: .word RAMDISK +vid_mode: .word SVGA_MODE +root_dev: .word ROOT_DEV +boot_flag: .word 0xAA55 diff --git a/trunk/arch/x86_64/boot/compressed/Makefile b/trunk/arch/x86_64/boot/compressed/Makefile index c9f2da7496c1..705a3e33d7e1 100644 --- a/trunk/arch/x86_64/boot/compressed/Makefile +++ b/trunk/arch/x86_64/boot/compressed/Makefile @@ -7,12 +7,11 @@ # targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +EXTRA_AFLAGS := -traditional -CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \ - -fno-strict-aliasing -fPIC -mcmodel=small \ - $(call cc-option, -ffreestanding) \ - $(call cc-option, -fno-stack-protector) -AFLAGS := $(CFLAGS) -D__ASSEMBLY__ +# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with +# -m32 +CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin LDFLAGS := -m elf_x86_64 LDFLAGS_vmlinux := -T diff --git a/trunk/arch/x86_64/boot/compressed/head.S b/trunk/arch/x86_64/boot/compressed/head.S index 1312bfaff306..f9d5692a0106 100644 --- a/trunk/arch/x86_64/boot/compressed/head.S +++ b/trunk/arch/x86_64/boot/compressed/head.S @@ -46,10 +46,10 @@ startup_32: * at and where we were actually loaded at. This can only be done * with a short local call on x86. Nothing else will tell us what * address we are running at. The reserved chunk of the real-mode - * data at 0x1e4 (defined as a scratch field) are used as the stack - * for this calculation. Only 4 bytes are needed. + * data at 0x34-0x3f are used as the stack for this calculation. + * Only 4 bytes are needed. */ - leal (0x1e4+4)(%esi), %esp + leal 0x40(%esi), %esp call 1f 1: popl %ebp subl $1b, %ebp diff --git a/trunk/arch/x86_64/boot/install.sh b/trunk/arch/x86_64/boot/install.sh new file mode 100644 index 000000000000..baaa2369bdb8 --- /dev/null +++ b/trunk/arch/x86_64/boot/install.sh @@ -0,0 +1,2 @@ +#!/bin/sh +. $srctree/arch/i386/boot/install.sh diff --git a/trunk/arch/x86_64/boot/mtools.conf.in b/trunk/arch/x86_64/boot/mtools.conf.in new file mode 100644 index 000000000000..efd6d2490c1d --- /dev/null +++ b/trunk/arch/x86_64/boot/mtools.conf.in @@ -0,0 +1,17 @@ +# +# mtools configuration file for "make (b)zdisk" +# + +# Actual floppy drive +drive a: + file="/dev/fd0" + +# 1.44 MB floppy disk image +drive v: + file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter + +# 2.88 MB floppy disk image (mostly for virtual uses) +drive w: + file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter + + diff --git a/trunk/arch/x86_64/boot/setup.S b/trunk/arch/x86_64/boot/setup.S new file mode 100644 index 000000000000..e9e33f949697 --- /dev/null +++ b/trunk/arch/x86_64/boot/setup.S @@ -0,0 +1,826 @@ +/* + * setup.S Copyright (C) 1991, 1992 Linus Torvalds + * + * setup.s is responsible for getting the system data from the BIOS, + * and putting them into the appropriate places in system memory. + * both setup.s and system has been loaded by the bootblock. + * + * This code asks the bios for memory/disk/other parameters, and + * puts them in a "safe" place: 0x90000-0x901FF, ie where the + * boot-block used to be. It is then up to the protected mode + * system to read them from there before the area is overwritten + * for buffer-blocks. + * + * Move PS/2 aux init code to psaux.c + * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 + * + * some changes and additional features by Christoph Niemann, + * March 1993/June 1994 (Christoph.Niemann@linux.org) + * + * add APM BIOS checking by Stephen Rothwell, May 1994 + * (sfr@canb.auug.org.au) + * + * High load stuff, initrd support and position independency + * by Hans Lermen & Werner Almesberger, February 1996 + * , + * + * Video handling moved to video.S by Martin Mares, March 1996 + * + * + * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david + * parsons) to avoid loadlin confusion, July 1997 + * + * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. + * + * + * Fix to work around buggy BIOSes which don't use carry bit correctly + * and/or report extended memory in CX/DX for e801h memory size detection + * call. As a result the kernel got wrong figures. The int15/e801h docs + * from Ralf Brown interrupt list seem to indicate AX/BX should be used + * anyway. So to avoid breaking many machines (presumably there was a reason + * to orginally use CX/DX instead of AX/BX), we do a kludge to see + * if CX/DX have been changed in the e801 call and if so use AX/BX . + * Michael Miller, April 2001 + * + * Added long mode checking and SSE force. March 2003, Andi Kleen. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Signature words to ensure LILO loaded us right */ +#define SIG1 0xAA55 +#define SIG2 0x5A5A + +INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way +SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). +SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment + # ... and the former contents of CS + +DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 + +.code16 +.globl begtext, begdata, begbss, endtext, enddata, endbss + +.text +begtext: +.data +begdata: +.bss +begbss: +.text + +start: + jmp trampoline + +# This is the setup header, and it must start at %cs:2 (old 0x9020:2) + + .ascii "HdrS" # header signature + .word 0x0206 # header version number (>= 0x0105) + # or else old loadlin-1.5 will fail) +realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +start_sys_seg: .word SYSSEG + .word kernel_version # pointing to kernel version string + # above section of header is compatible + # with loadlin-1.5 (header v1.5). Don't + # change it. + +type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, + # Bootlin, SYSLX, bootsect...) + # See Documentation/i386/boot.txt for + # assigned ids + +# flags, unused bits must be zero (RFU) bit within loadflags +loadflags: +LOADED_HIGH = 1 # If set, the kernel is loaded high +CAN_USE_HEAP = 0x80 # If set, the loader also has set + # heap_end_ptr to tell how much + # space behind setup.S can be used for + # heap purposes. + # Only the loader knows what is free +#ifndef __BIG_KERNEL__ + .byte 0 +#else + .byte LOADED_HIGH +#endif + +setup_move_size: .word 0x8000 # size to move, when setup is not + # loaded at 0x90000. We will move setup + # to 0x90000 then just before jumping + # into the kernel. However, only the + # loader knows how much data behind + # us also needs to be loaded. + +code32_start: # here loaders can put a different + # start address for 32-bit code. +#ifndef __BIG_KERNEL__ + .long 0x1000 # 0x1000 = default for zImage +#else + .long 0x100000 # 0x100000 = default for big kernel +#endif + +ramdisk_image: .long 0 # address of loaded ramdisk image + # Here the loader puts the 32-bit + # address where it loaded the image. + # This only will be read by the kernel. + +ramdisk_size: .long 0 # its size in bytes + +bootsect_kludge: + .long 0 # obsolete + +heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) + # space from here (exclusive) down to + # end of setup code can be used by setup + # for local heap purposes. + +pad1: .word 0 +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + +ramdisk_max: .long 0xffffffff +kernel_alignment: .long 0x200000 # physical addr alignment required for + # protected mode relocatable kernel +#ifdef CONFIG_RELOCATABLE +relocatable_kernel: .byte 1 +#else +relocatable_kernel: .byte 0 +#endif +pad2: .byte 0 +pad3: .word 0 + +cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, + #added with boot protocol + #version 2.06 + +trampoline: call start_of_setup + .align 16 + # The offset at this point is 0x240 + .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) +# End of setup header ##################################################### + +start_of_setup: +# Bootlin depends on this being done early + movw $0x01500, %ax + movb $0x81, %dl + int $0x13 + +#ifdef SAFE_RESET_DISK_CONTROLLER +# Reset the disk controller. + movw $0x0000, %ax + movb $0x80, %dl + int $0x13 +#endif + +# Set %ds = %cs, we know that SETUPSEG = %cs at this point + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds +# Check signature at end of setup + cmpw $SIG1, setup_sig1 + jne bad_sig + + cmpw $SIG2, setup_sig2 + jne bad_sig + + jmp good_sig1 + +# Routine to print asciiz string at ds:si +prtstr: + lodsb + andb %al, %al + jz fin + + call prtchr + jmp prtstr + +fin: ret + +# Space printing +prtsp2: call prtspc # Print double space +prtspc: movb $0x20, %al # Print single space (note: fall-thru) + +prtchr: + pushw %ax + pushw %cx + movw $0007,%bx + movw $0x01, %cx + movb $0x0e, %ah + int $0x10 + popw %cx + popw %ax + ret + +beep: movb $0x07, %al + jmp prtchr + +no_sig_mess: .string "No setup signature found ..." + +good_sig1: + jmp good_sig + +# We now have to find the rest of the setup code/data +bad_sig: + movw %cs, %ax # SETUPSEG + subw $DELTA_INITSEG, %ax # INITSEG + movw %ax, %ds + xorb %bh, %bh + movb (497), %bl # get setup sect from bootsect + subw $4, %bx # LILO loads 4 sectors of setup + shlw $8, %bx # convert to words (1sect=2^8 words) + movw %bx, %cx + shrw $3, %bx # convert to segment + addw $SYSSEG, %bx + movw %bx, %cs:start_sys_seg +# Move rest of setup code/data to here + movw $2048, %di # four sectors loaded by LILO + subw %si, %si + movw %cs, %ax # aka SETUPSEG + movw %ax, %es + movw $SYSSEG, %ax + movw %ax, %ds + rep + movsw + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + cmpw $SIG1, setup_sig1 + jne no_sig + + cmpw $SIG2, setup_sig2 + jne no_sig + + jmp good_sig + +no_sig: + lea no_sig_mess, %si + call prtstr + +no_sig_loop: + jmp no_sig_loop + +good_sig: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds +# Check if an old loader tries to load a big-kernel + testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? + jz loader_ok # No, no danger for old loaders. + + cmpb $0, %cs:type_of_loader # Do we have a loader that + # can deal with us? + jnz loader_ok # Yes, continue. + + pushw %cs # No, we have an old loader, + popw %ds # die. + lea loader_panic_mess, %si + call prtstr + + jmp no_sig_loop + +loader_panic_mess: .string "Wrong loader, giving up..." + +loader_ok: + /* check for long mode. */ + /* we have to do this before the VESA setup, otherwise the user + can't see the error message. */ + + pushw %ds + movw %cs,%ax + movw %ax,%ds + + call verify_cpu + testl %eax,%eax + jz sse_ok + +no_longmode: + call beep + lea long_mode_panic,%si + call prtstr +no_longmode_loop: + jmp no_longmode_loop +long_mode_panic: + .string "Your CPU does not support long mode. Use a 32bit distribution." + .byte 0 + +#include "../kernel/verify_cpu.S" +sse_ok: + popw %ds + +# tell BIOS we want to go to long mode + movl $0xec00,%eax # declare target operating mode + movl $2,%ebx # long mode + int $0x15 + +# Get memory size (extended mem, kB) + + xorl %eax, %eax + movl %eax, (0x1e0) +#ifndef STANDARD_MEMORY_BIOS_CALL + movb %al, (E820NR) +# Try three different memory detection schemes. First, try +# e820h, which lets us assemble a memory map, then try e801h, +# which returns a 32-bit memory size, and finally 88h, which +# returns 0-64m + +# method E820H: +# the memory map from hell. e820h returns memory classified into +# a whole bunch of different types, and allows memory holes and +# everything. We scan through this memory map and build a list +# of the first 32 memory areas, which we return at [E820MAP]. +# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. + +#define SMAP 0x534d4150 + +meme820: + xorl %ebx, %ebx # continuation counter + movw $E820MAP, %di # point into the whitelist + # so we can have the bios + # directly write into it. + +jmpe820: + movl $0x0000e820, %eax # e820, upper word zeroed + movl $SMAP, %edx # ascii 'SMAP' + movl $20, %ecx # size of the e820rec + pushw %ds # data record. + popw %es + int $0x15 # make the call + jc bail820 # fall to e801 if it fails + + cmpl $SMAP, %eax # check the return is `SMAP' + jne bail820 # fall to e801 if it fails + +# cmpl $1, 16(%di) # is this usable memory? +# jne again820 + + # If this is usable memory, we save it by simply advancing %di by + # sizeof(e820rec). + # +good820: + movb (E820NR), %al # up to 128 entries + cmpb $E820MAX, %al + jae bail820 + + incb (E820NR) + movw %di, %ax + addw $20, %ax + movw %ax, %di +again820: + cmpl $0, %ebx # check to see if + jne jmpe820 # %ebx is set to EOF +bail820: + + +# method E801H: +# memory size is in 1k chunksizes, to avoid confusing loadlin. +# we store the 0xe801 memory size in a completely different place, +# because it will most likely be longer than 16 bits. +# (use 1e0 because that's what Larry Augustine uses in his +# alternative new memory detection scheme, and it's sensible +# to write everything into the same place.) + +meme801: + stc # fix to work around buggy + xorw %cx,%cx # BIOSes which don't clear/set + xorw %dx,%dx # carry on pass/error of + # e801h memory size call + # or merely pass cx,dx though + # without changing them. + movw $0xe801, %ax + int $0x15 + jc mem88 + + cmpw $0x0, %cx # Kludge to handle BIOSes + jne e801usecxdx # which report their extended + cmpw $0x0, %dx # memory in AX/BX rather than + jne e801usecxdx # CX/DX. The spec I have read + movw %ax, %cx # seems to indicate AX/BX + movw %bx, %dx # are more reasonable anyway... + +e801usecxdx: + andl $0xffff, %edx # clear sign extend + shll $6, %edx # and go from 64k to 1k chunks + movl %edx, (0x1e0) # store extended memory size + andl $0xffff, %ecx # clear sign extend + addl %ecx, (0x1e0) # and add lower memory into + # total size. + +# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +# 64mb, depending on the bios) in ax. +mem88: + +#endif + movb $0x88, %ah + int $0x15 + movw %ax, (2) + +# Set the keyboard repeat rate to the max + movw $0x0305, %ax + xorw %bx, %bx + int $0x16 + +# Check for video adapter and its parameters and allow the +# user to browse video modes. + call video # NOTE: we need %ds pointing + # to bootsector + +# Get hd0 data... + xorw %ax, %ax + movw %ax, %ds + ldsw (4 * 0x41), %si + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + pushw %ax + movw %ax, %es + movw $0x0080, %di + movw $0x10, %cx + pushw %cx + cld + rep + movsb +# Get hd1 data... + xorw %ax, %ax + movw %ax, %ds + ldsw (4 * 0x46), %si + popw %cx + popw %es + movw $0x0090, %di + rep + movsb +# Check that there IS a hd1 :-) + movw $0x01500, %ax + movb $0x81, %dl + int $0x13 + jc no_disk1 + + cmpb $3, %ah + je is_disk1 + +no_disk1: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + xorw %ax, %ax + cld + rep + stosb +is_disk1: + +# Check for PS/2 pointing device + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds + movb $0, (0x1ff) # default is no pointing device + int $0x11 # int 0x11: equipment list + testb $0x04, %al # check if mouse installed + jz no_psmouse + + movb $0xAA, (0x1ff) # device present +no_psmouse: + +#include "../../i386/boot/edd.S" + +# Now we want to move to protected mode ... + cmpw $0, %cs:realmode_swtch + jz rmodeswtch_normal + + lcall *%cs:realmode_swtch + + jmp rmodeswtch_end + +rmodeswtch_normal: + pushw %cs + call default_switch + +rmodeswtch_end: +# we get the code32 start address and modify the below 'jmpi' +# (loader may have changed it) + movl %cs:code32_start, %eax + movl %eax, %cs:code32 + +# Now we move the system to its rightful place ... but we check if we have a +# big-kernel. In that case we *must* not move it ... + testb $LOADED_HIGH, %cs:loadflags + jz do_move0 # .. then we have a normal low + # loaded zImage + # .. or else we have a high + # loaded bzImage + jmp end_move # ... and we skip moving + +do_move0: + movw $0x100, %ax # start of destination segment + movw %cs, %bp # aka SETUPSEG + subw $DELTA_INITSEG, %bp # aka INITSEG + movw %cs:start_sys_seg, %bx # start of source segment + cld +do_move: + movw %ax, %es # destination segment + incb %ah # instead of add ax,#0x100 + movw %bx, %ds # source segment + addw $0x100, %bx + subw %di, %di + subw %si, %si + movw $0x800, %cx + rep + movsw + cmpw %bp, %bx # assume start_sys_seg > 0x200, + # so we will perhaps read one + # page more than needed, but + # never overwrite INITSEG + # because destination is a + # minimum one page below source + jb do_move + +end_move: +# then we load the segment descriptors + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + +# Check whether we need to be downward compatible with version <=201 + cmpl $0, cmd_line_ptr + jne end_move_self # loader uses version >=202 features + cmpb $0x20, type_of_loader + je end_move_self # bootsect loader, we know of it + +# Boot loader doesnt support boot protocol version 2.02. +# If we have our code not at 0x90000, we need to move it there now. +# We also then need to move the params behind it (commandline) +# Because we would overwrite the code on the current IP, we move +# it in two steps, jumping high after the first one. + movw %cs, %ax + cmpw $SETUPSEG, %ax + je end_move_self + + cli # make sure we really have + # interrupts disabled ! + # because after this the stack + # should not be used + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ss, %dx + cmpw %ax, %dx + jb move_self_1 + + addw $INITSEG, %dx + subw %ax, %dx # this will go into %ss after + # the move +move_self_1: + movw %ax, %ds + movw $INITSEG, %ax # real INITSEG + movw %ax, %es + movw %cs:setup_move_size, %cx + std # we have to move up, so we use + # direction down because the + # areas may overlap + movw %cx, %di + decw %di + movw %di, %si + subw $move_self_here+0x200, %cx + rep + movsb + ljmp $SETUPSEG, $move_self_here + +move_self_here: + movw $move_self_here+0x200, %cx + rep + movsb + movw $SETUPSEG, %ax + movw %ax, %ds + movw %dx, %ss +end_move_self: # now we are at the right place + lidt idt_48 # load idt with 0,0 + xorl %eax, %eax # Compute gdt_base + movw %ds, %ax # (Convert %ds:gdt to a linear ptr) + shll $4, %eax + addl $gdt, %eax + movl %eax, (gdt_48+2) + lgdt gdt_48 # load gdt with whatever is + # appropriate + +# that was painless, now we enable a20 + call empty_8042 + + movb $0xD1, %al # command write + outb %al, $0x64 + call empty_8042 + + movb $0xDF, %al # A20 on + outb %al, $0x60 + call empty_8042 + +# +# You must preserve the other bits here. Otherwise embarrasing things +# like laptops powering off on boot happen. Corrected version by Kira +# Brown from Linux 2.2 +# + inb $0x92, %al # + orb $02, %al # "fast A20" version + outb %al, $0x92 # some chips have only this + +# wait until a20 really *is* enabled; it can take a fair amount of +# time on certain systems; Toshiba Tecras are known to have this +# problem. The memory location used here (0x200) is the int 0x80 +# vector, which should be safe to use. + + xorw %ax, %ax # segment 0x0000 + movw %ax, %fs + decw %ax # segment 0xffff (HMA) + movw %ax, %gs +a20_wait: + incw %ax # unused memory location <0xfff0 + movw %ax, %fs:(0x200) # we use the "int 0x80" vector + cmpw %gs:(0x210), %ax # and its corresponding HMA addr + je a20_wait # loop until no longer aliased + +# make sure any possible coprocessor is properly reset.. + xorw %ax, %ax + outb %al, $0xf0 + call delay + + outb %al, $0xf1 + call delay + +# well, that went ok, I hope. Now we mask all interrupts - the rest +# is done in init_IRQ(). + movb $0xFF, %al # mask all interrupts for now + outb %al, $0xA1 + call delay + + movb $0xFB, %al # mask all irq's but irq2 which + outb %al, $0x21 # is cascaded + +# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't +# need no steenking BIOS anyway (except for the initial loading :-). +# The BIOS-routine wants lots of unnecessary data, and it's less +# "interesting" anyway. This is how REAL programmers do it. +# +# Well, now's the time to actually move into protected mode. To make +# things as simple as possible, we do no register set-up or anything, +# we let the gnu-compiled 32-bit programs do that. We just jump to +# absolute address 0x1000 (or the loader supplied one), +# in 32-bit protected mode. +# +# Note that the short jump isn't strictly needed, although there are +# reasons why it might be a good idea. It won't hurt in any case. + movw $1, %ax # protected mode (PE) bit + lmsw %ax # This is it! + jmp flush_instr + +flush_instr: + xorw %bx, %bx # Flag to indicate a boot + xorl %esi, %esi # Pointer to real-mode code + movw %cs, %si + subw $DELTA_INITSEG, %si + shll $4, %esi # Convert to 32-bit pointer +# NOTE: For high loaded big kernels we need a +# jmpi 0x100000,__KERNEL_CS +# +# but we yet haven't reloaded the CS register, so the default size +# of the target offset still is 16 bit. +# However, using an operand prefix (0x66), the CPU will properly +# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference +# Manual, Mixing 16-bit and 32-bit code, page 16-6) + + .byte 0x66, 0xea # prefix + jmpi-opcode +code32: .long 0x1000 # will be set to 0x100000 + # for big kernels + .word __KERNEL_CS + +# Here's a bunch of information about your current kernel.. +kernel_version: .ascii UTS_RELEASE + .ascii " (" + .ascii LINUX_COMPILE_BY + .ascii "@" + .ascii LINUX_COMPILE_HOST + .ascii ") " + .ascii UTS_VERSION + .byte 0 + +# This is the default real mode switch routine. +# to be called just before protected mode transition +default_switch: + cli # no interrupts allowed ! + movb $0x80, %al # disable NMI for bootup + # sequence + outb %al, $0x70 + lret + + +# This routine checks that the keyboard command queue is empty +# (after emptying the output buffers) +# +# Some machines have delusions that the keyboard buffer is always full +# with no keyboard attached... +# +# If there is no keyboard controller, we will usually get 0xff +# to all the reads. With each IO taking a microsecond and +# a timeout of 100,000 iterations, this can take about half a +# second ("delay" == outb to port 0x80). That should be ok, +# and should also be plenty of time for a real keyboard controller +# to empty. +# + +empty_8042: + pushl %ecx + movl $100000, %ecx + +empty_8042_loop: + decl %ecx + jz empty_8042_end_loop + + call delay + + inb $0x64, %al # 8042 status port + testb $1, %al # output buffer? + jz no_output + + call delay + inb $0x60, %al # read it + jmp empty_8042_loop + +no_output: + testb $2, %al # is input buffer full? + jnz empty_8042_loop # yes - loop +empty_8042_end_loop: + popl %ecx + ret + +# Read the cmos clock. Return the seconds in al +gettime: + pushw %cx + movb $0x02, %ah + int $0x1a + movb %dh, %al # %dh contains the seconds + andb $0x0f, %al + movb %dh, %ah + movb $0x04, %cl + shrb %cl, %ah + aad + popw %cx + ret + +# Delay is needed after doing I/O +delay: + outb %al,$0x80 + ret + +# Descriptor tables +gdt: + .word 0, 0, 0, 0 # dummy + + .word 0, 0, 0, 0 # unused + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9A00 # code read/exec + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9200 # data read/write + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) +gdt_end: +idt_48: + .word 0 # idt limit = 0 + .word 0, 0 # idt base = 0L +gdt_48: + .word gdt_end-gdt-1 # gdt limit + .word 0, 0 # gdt base (filled in later) + +# Include video setup & detection code + +#include "../../i386/boot/video.S" + +# Setup signature -- must be last +setup_sig1: .word SIG1 +setup_sig2: .word SIG2 + +# After this point, there is some free space which is used by the video mode +# handling code to store the temporary mode table (not used by the kernel). + +modelist: + +.text +endtext: +.data +enddata: +.bss +endbss: diff --git a/trunk/arch/x86_64/boot/tools/build.c b/trunk/arch/x86_64/boot/tools/build.c new file mode 100644 index 000000000000..eae86691709a --- /dev/null +++ b/trunk/arch/x86_64/boot/tools/build.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1997 Martin Mares + */ + +/* + * This file builds a disk-image from three different files: + * + * - bootsect: compatibility mbr which prints an error message if + * someone tries to boot the kernel directly. + * - setup: 8086 machine code, sets up system parm + * - system: 80386 code for actual system + * + * It does some checking that all files are of the correct type, and + * just writes the result to stdout, removing headers and padding to + * the right amount. It also writes some system data to stderr. + */ + +/* + * Changes by tytso to allow root device specification + * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 + * Cross compiling fixes by Gertjan van Wingerde, July 1996 + * Rewritten by Martin Mares, April 1997 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long u32; + +#define DEFAULT_MAJOR_ROOT 0 +#define DEFAULT_MINOR_ROOT 0 + +/* Minimal number of setup sectors (see also bootsect.S) */ +#define SETUP_SECTS 4 + +byte buf[1024]; +int fd; +int is_big_kernel; + +void die(const char * str, ...) +{ + va_list args; + va_start(args, str); + vfprintf(stderr, str, args); + fputc('\n', stderr); + exit(1); +} + +void file_open(const char *name) +{ + if ((fd = open(name, O_RDONLY, 0)) < 0) + die("Unable to open `%s': %m", name); +} + +void usage(void) +{ + die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char ** argv) +{ + unsigned int i, c, sz, setup_sectors; + u32 sys_size; + byte major_root, minor_root; + struct stat sb; + + if (argc > 2 && !strcmp(argv[1], "-b")) + { + is_big_kernel = 1; + argc--, argv++; + } + if ((argc < 4) || (argc > 5)) + usage(); + if (argc > 4) { + if (!strcmp(argv[4], "CURRENT")) { + if (stat("/", &sb)) { + perror("/"); + die("Couldn't stat /"); + } + major_root = major(sb.st_dev); + minor_root = minor(sb.st_dev); + } else if (strcmp(argv[4], "FLOPPY")) { + if (stat(argv[4], &sb)) { + perror(argv[4]); + die("Couldn't stat root device."); + } + major_root = major(sb.st_rdev); + minor_root = minor(sb.st_rdev); + } else { + major_root = 0; + minor_root = 0; + } + } else { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + + file_open(argv[1]); + i = read(fd, buf, sizeof(buf)); + fprintf(stderr,"Boot sector %d bytes.\n",i); + if (i != 512) + die("Boot block must be exactly 512 bytes"); + if (buf[510] != 0x55 || buf[511] != 0xaa) + die("Boot block hasn't got boot flag (0xAA55)"); + buf[508] = minor_root; + buf[509] = major_root; + if (write(1, buf, 512) != 512) + die("Write call failed"); + close (fd); + + file_open(argv[2]); /* Copy the setup code */ + for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) + if (write(1, buf, c) != c) + die("Write call failed"); + if (c != 0) + die("read-error on `setup'"); + close (fd); + + setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ + /* for compatibility with ancient versions of LILO. */ + if (setup_sectors < SETUP_SECTS) + setup_sectors = SETUP_SECTS; + fprintf(stderr, "Setup is %d bytes.\n", i); + memset(buf, 0, sizeof(buf)); + while (i < setup_sectors * 512) { + c = setup_sectors * 512 - i; + if (c > sizeof(buf)) + c = sizeof(buf); + if (write(1, buf, c) != c) + die("Write call failed"); + i += c; + } + + file_open(argv[3]); + if (fstat (fd, &sb)) + die("Unable to stat `%s': %m", argv[3]); + sz = sb.st_size; + fprintf (stderr, "System is %d kB\n", sz/1024); + sys_size = (sz + 15) / 16; + if (!is_big_kernel && sys_size > DEF_SYSSIZE) + die("System is too big. Try using bzImage or modules."); + while (sz > 0) { + int l, n; + + l = (sz > sizeof(buf)) ? sizeof(buf) : sz; + if ((n=read(fd, buf, l)) != l) { + if (n < 0) + die("Error reading %s: %m", argv[3]); + else + die("%s: Unexpected EOF", argv[3]); + } + if (write(1, buf, l) != l) + die("Write failed"); + sz -= l; + } + close(fd); + + if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ + die("Output: seek failed"); + buf[0] = setup_sectors; + if (write(1, buf, 1) != 1) + die("Write of setup sector count failed"); + if (lseek(1, 500, SEEK_SET) != 500) + die("Output: seek failed"); + buf[0] = (sys_size & 0xff); + buf[1] = ((sys_size >> 8) & 0xff); + buf[2] = ((sys_size >> 16) & 0xff); + buf[3] = ((sys_size >> 24) & 0xff); + if (write(1, buf, 4) != 4) + die("Write of image length failed"); + + return 0; /* Everything is OK */ +} diff --git a/trunk/arch/x86_64/kernel/Makefile b/trunk/arch/x86_64/kernel/Makefile index 47f1dc30bf56..de1de8a2fd84 100644 --- a/trunk/arch/x86_64/kernel/Makefile +++ b/trunk/arch/x86_64/kernel/Makefile @@ -44,7 +44,6 @@ obj-$(CONFIG_PCI) += early-quirks.o obj-y += topology.o obj-y += intel_cacheinfo.o -obj-y += addon_cpuid_features.o obj-y += pcspeaker.o CFLAGS_vsyscall.o := $(PROFILING) -g0 @@ -56,7 +55,6 @@ cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o topology-y += ../../i386/kernel/topology.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o -addon_cpuid_features-y += ../../i386/kernel/cpu/addon_cpuid_features.o quirks-y += ../../i386/kernel/quirks.o i8237-y += ../../i386/kernel/i8237.o msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o diff --git a/trunk/arch/x86_64/kernel/setup.c b/trunk/arch/x86_64/kernel/setup.c index 33ef718f8cb5..eb6524f3ac29 100644 --- a/trunk/arch/x86_64/kernel/setup.c +++ b/trunk/arch/x86_64/kernel/setup.c @@ -846,8 +846,6 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_capability[2] = cpuid_edx(0x80860001); } - init_scattered_cpuid_features(c); - c->apicid = phys_pkg_id(0); /* @@ -933,7 +931,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", + "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, /* AMD-defined */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -949,11 +947,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Other (Linux-defined) */ - "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", - NULL, NULL, NULL, NULL, - "constant_tsc", "up", NULL, "arch_perfmon", - "pebs", "bts", NULL, "sync_rdtsc", - "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL, + "constant_tsc", NULL, NULL, + "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ @@ -964,7 +961,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* VIA/Cyrix/Centaur-defined */ NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", - "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -975,12 +972,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) "osvw", "ibs", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Auxiliary (Linux-defined) */ - "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static char *x86_power_flags[] = { "ts", /* temperature sensor */ diff --git a/trunk/arch/x86_64/kernel/verify_cpu.S b/trunk/arch/x86_64/kernel/verify_cpu.S index 45b6f8a975a1..e035f5948199 100644 --- a/trunk/arch/x86_64/kernel/verify_cpu.S +++ b/trunk/arch/x86_64/kernel/verify_cpu.S @@ -37,6 +37,20 @@ verify_cpu: pushl $0 # Kill any dangerous flags popfl + /* minimum CPUID flags for x86-64 as defined by AMD */ +#define M(x) (1<<(x)) +#define M2(a,b) M(a)|M(b) +#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d) + +#define SSE_MASK \ + (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2)) +#define REQUIRED_MASK1 \ + (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\ + M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\ + M(X86_FEATURE_FXSR)) +#define REQUIRED_MASK2 \ + (M(X86_FEATURE_LM - 32)) + pushfl # standard way to check for cpuid popl %eax movl %eax,%ebx @@ -65,8 +79,8 @@ verify_cpu: verify_cpu_noamd: movl $0x1,%eax # Does the cpu have what it takes cpuid - andl $REQUIRED_MASK0,%edx - xorl $REQUIRED_MASK0,%edx + andl $REQUIRED_MASK1,%edx + xorl $REQUIRED_MASK1,%edx jnz verify_cpu_no_longmode movl $0x80000000,%eax # See if extended cpuid is implemented @@ -76,8 +90,8 @@ verify_cpu_noamd: movl $0x80000001,%eax # Does the cpu have what it takes cpuid - andl $REQUIRED_MASK1,%edx - xorl $REQUIRED_MASK1,%edx + andl $REQUIRED_MASK2,%edx + xorl $REQUIRED_MASK2,%edx jnz verify_cpu_no_longmode verify_cpu_sse_test: diff --git a/trunk/drivers/i2c/algos/Kconfig b/trunk/drivers/i2c/algos/Kconfig index 014dfa575be7..58899078810b 100644 --- a/trunk/drivers/i2c/algos/Kconfig +++ b/trunk/drivers/i2c/algos/Kconfig @@ -34,6 +34,10 @@ config I2C_ALGOPCA This support is also available as a module. If so, the module will be called i2c-algo-pca. +config I2C_ALGO8XX + tristate "MPC8xx CPM I2C interface" + depends on 8xx + config I2C_ALGO_SGI tristate "I2C SGI interfaces" depends on SGI_IP22 || SGI_IP32 || X86_VISWS diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index fcde9bab5b96..838dc1c19d61 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -207,7 +207,6 @@ config I2C_PIIX4 ATI IXP300 ATI IXP400 ATI SB600 - ATI SB700 Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 @@ -391,6 +390,11 @@ config I2C_PROSAVAGE This support is also available as a module. If so, the module will be called i2c-prosavage. +config I2C_RPXLITE + tristate "Embedded Planet RPX Lite/Classic support" + depends on RPXLITE || RPXCLASSIC + select I2C_ALGO8XX + config I2C_S3C2410 tristate "S3C2410 I2C Driver" depends on ARCH_S3C2410 @@ -508,22 +512,6 @@ config I2C_SIS96X This driver can also be built as a module. If so, the module will be called i2c-sis96x. -config I2C_TAOS_EVM - tristate "TAOS evaluation module" - depends on EXPERIMENTAL - select SERIO - select SERIO_SERPORT - default n - help - This supports TAOS evaluation modules on serial port. In order to - use this driver, you will need the inputattach tool, which is part - of the input-utils package. - - If unsure, say N. - - This support is also available as a module. If so, the module - will be called i2c-taos-evm. - config I2C_STUB tristate "I2C/SMBus Test Stub" depends on EXPERIMENTAL && m @@ -647,13 +635,4 @@ config I2C_PNX This driver can also be built as a module. If so, the module will be called i2c-pnx. -config I2C_PMCMSP - tristate "PMC MSP I2C TWI Controller" - depends on PMC_MSP - help - This driver supports the PMC TWI controller on MSP devices. - - This driver can also be built as module. If so, the module - will be called i2c-pmcmsp. - endmenu diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile index a6db4e38bda8..14d1432f698b 100644 --- a/trunk/drivers/i2c/busses/Makefile +++ b/trunk/drivers/i2c/busses/Makefile @@ -32,10 +32,10 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o -obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o +obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o @@ -44,7 +44,6 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o -obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o diff --git a/trunk/drivers/i2c/busses/i2c-gpio.c b/trunk/drivers/i2c/busses/i2c-gpio.c index 025f19423faf..a7dd54654a9a 100644 --- a/trunk/drivers/i2c/busses/i2c-gpio.c +++ b/trunk/drivers/i2c/busses/i2c-gpio.c @@ -63,14 +63,14 @@ static void i2c_gpio_setscl_val(void *data, int state) gpio_set_value(pdata->scl_pin, state); } -static int i2c_gpio_getsda(void *data) +int i2c_gpio_getsda(void *data) { struct i2c_gpio_platform_data *pdata = data; return gpio_get_value(pdata->sda_pin); } -static int i2c_gpio_getscl(void *data) +int i2c_gpio_getscl(void *data) { struct i2c_gpio_platform_data *pdata = data; @@ -142,13 +142,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev) adap->algo_data = bit_data; adap->dev.parent = &pdev->dev; - /* - * If "dev->id" is negative we consider it as zero. - * The reason to do so is to avoid sysfs names that only make - * sense when there are multiple adapters. - */ - adap->nr = pdev->id >= 0 ? pdev->id : 0; - ret = i2c_bit_add_numbered_bus(adap); + ret = i2c_bit_add_bus(adap); if (ret) goto err_add_bus; diff --git a/trunk/drivers/i2c/busses/i2c-i801.c b/trunk/drivers/i2c/busses/i2c-i801.c index 8f5c686123b8..611b57192c96 100644 --- a/trunk/drivers/i2c/busses/i2c-i801.c +++ b/trunk/drivers/i2c/busses/i2c-i801.c @@ -22,12 +22,12 @@ /* SUPPORTED DEVICES PCI ID - 82801AA 2413 - 82801AB 2423 - 82801BA 2443 - 82801CA/CAM 2483 - 82801DB 24C3 (HW PEC supported) - 82801EB 24D3 (HW PEC supported) + 82801AA 2413 + 82801AB 2423 + 82801BA 2443 + 82801CA/CAM 2483 + 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) + 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) 6300ESB 25A4 ICH6 266A ICH7 27DA @@ -74,13 +74,6 @@ #define SMBHSTCFG_SMB_SMI_EN 2 #define SMBHSTCFG_I2C_EN 4 -/* Auxillary control register bits, ICH4+ only */ -#define SMBAUXCTL_CRC 1 -#define SMBAUXCTL_E32B 2 - -/* kill bit for SMBHSTCNT */ -#define SMBHSTCNT_KILL 2 - /* Other settings */ #define MAX_TIMEOUT 100 #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ @@ -98,15 +91,10 @@ #define I801_START 0x40 #define I801_PEC_EN 0x80 /* ICH4 only */ -/* I801 Hosts Status register bits */ -#define SMBHSTSTS_BYTE_DONE 0x80 -#define SMBHSTSTS_INUSE_STS 0x40 -#define SMBHSTSTS_SMBALERT_STS 0x20 -#define SMBHSTSTS_FAILED 0x10 -#define SMBHSTSTS_BUS_ERR 0x08 -#define SMBHSTSTS_DEV_ERR 0x04 -#define SMBHSTSTS_INTR 0x02 -#define SMBHSTSTS_HOST_BUSY 0x01 + +static int i801_transaction(void); +static int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command, int hwpec); static unsigned long i801_smba; static unsigned char i801_original_hstcfg; @@ -114,7 +102,7 @@ static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; -static int i801_transaction(int xact) +static int i801_transaction(void) { int temp; int result = 0; @@ -139,40 +127,33 @@ static int i801_transaction(int xact) } } - /* the current contents of SMBHSTCNT can be overwritten, since PEC, - * INTREN, SMBSCMD are passed in xact */ - outb_p(xact | I801_START, SMBHSTCNT); + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); /* We will always wait for a fraction of a second! */ do { msleep(1); temp = inb_p(SMBHSTSTS); - } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); result = -1; - /* try to stop the current command */ - dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); - outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); - msleep(1); - outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); } - if (temp & SMBHSTSTS_FAILED) { + if (temp & 0x10) { result = -1; dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); } - if (temp & SMBHSTSTS_BUS_ERR) { + if (temp & 0x08) { result = -1; dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " "until next hard reset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ } - if (temp & SMBHSTSTS_DEV_ERR) { + if (temp & 0x04) { result = -1; dev_dbg(&I801_dev->dev, "Error: no response!\n"); } @@ -191,70 +172,44 @@ static int i801_transaction(int xact) return result; } -/* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(void) -{ - int timeout = 0; - int temp; - - do { - msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((!(temp & SMBHSTSTS_INTR)) - && (timeout++ < MAX_TIMEOUT)); - - if (timeout >= MAX_TIMEOUT) { - dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); - } - outb_p(temp, SMBHSTSTS); -} - -static int i801_block_transaction_by_block(union i2c_smbus_data *data, - char read_write, int hwpec) -{ - int i, len; - - inb_p(SMBHSTCNT); /* reset the data buffer index */ - - /* Use 32-byte buffer to process this transaction */ - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - outb_p(len, SMBHSTDAT0); - for (i = 0; i < len; i++) - outb_p(data->block[i+1], SMBBLKDAT); - } - - if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | - I801_PEC_EN * hwpec)) - return -1; - - if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -1; - - data->block[0] = len; - for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT); - } - return 0; -} - -static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, - char read_write, int hwpec) +/* All-inclusive block transaction function */ +static int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command, int hwpec) { int i, len; int smbcmd; int temp; int result = 0; int timeout; - unsigned char errmask; + unsigned char hostc, errmask; - len = data->block[0]; + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ + pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(I801_dev, SMBHSTCFG, + hostc | SMBHSTCFG_I2C_EN); + } else { + dev_err(&I801_dev->dev, + "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); + return -1; + } + } if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 1) + len = 1; + if (len > 32) + len = 32; outb_p(len, SMBHSTDAT0); outb_p(data->block[1], SMBBLKDAT); + } else { + len = 32; /* max for reads */ + } + + if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { + /* set 32 byte buffer */ } for (i = 1; i <= len; i++) { @@ -272,13 +227,13 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, /* Make sure the SMBus host is ready to start transmitting */ temp = inb_p(SMBHSTSTS); if (i == 1) { - /* Erronenous conditions before transaction: + /* Erronenous conditions before transaction: * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - errmask = 0x9f; + errmask=0x9f; } else { - /* Erronenous conditions during transaction: + /* Erronenous conditions during transaction: * Failed, Bus_Err, Dev_Err, Intr */ - errmask = 0x1e; + errmask=0x1e; } if (temp & errmask) { dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " @@ -287,11 +242,14 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { dev_err(&I801_dev->dev, "Reset failed! (%02x)\n", temp); - return -1; + result = -1; + goto END; } - if (i != 1) + if (i != 1) { /* if die in middle of block transaction, fail */ - return -1; + result = -1; + goto END; + } } if (i == 1) @@ -303,38 +261,33 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, msleep(1); temp = inb_p(SMBHSTSTS); } - while ((!(temp & SMBHSTSTS_BYTE_DONE)) - && (timeout++ < MAX_TIMEOUT)); + while ((!(temp & 0x80)) + && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - /* try to stop the current command */ - dev_dbg(&I801_dev->dev, "Terminating the current " - "operation\n"); - outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); - msleep(1); - outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), - SMBHSTCNT); result = -1; dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); } - if (temp & SMBHSTSTS_FAILED) { + if (temp & 0x10) { result = -1; dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); - } else if (temp & SMBHSTSTS_BUS_ERR) { + } else if (temp & 0x08) { result = -1; dev_err(&I801_dev->dev, "Bus collision!\n"); - } else if (temp & SMBHSTSTS_DEV_ERR) { + } else if (temp & 0x04) { result = -1; dev_dbg(&I801_dev->dev, "Error: no response!\n"); } if (i == 1 && read_write == I2C_SMBUS_READ) { len = inb_p(SMBHSTDAT0); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -1; + if (len < 1) + len = 1; + if (len > 32) + len = 32; data->block[0] = len; } @@ -357,58 +310,25 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); if (result < 0) - return result; + goto END; } - return result; -} -static int i801_set_block_buffer_mode(void) -{ - outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL); - if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0) - return -1; - return 0; -} - -/* Block transaction function */ -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command, int hwpec) -{ - int result = 0; - unsigned char hostc; + if (hwpec) { + /* wait for INTR bit as advised by Intel */ + timeout = 0; + do { + msleep(1); + temp = inb_p(SMBHSTSTS); + } while ((!(temp & 0x02)) + && (timeout++ < MAX_TIMEOUT)); - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); - pci_write_config_byte(I801_dev, SMBHSTCFG, - hostc | SMBHSTCFG_I2C_EN); - } else { - dev_err(&I801_dev->dev, - "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); - return -1; + if (timeout >= MAX_TIMEOUT) { + dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); } + outb_p(temp, SMBHSTSTS); } - - if (read_write == I2C_SMBUS_WRITE) { - if (data->block[0] < 1) - data->block[0] = 1; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - } else { - data->block[0] = 32; /* max for reads */ - } - - if (isich4 && i801_set_block_buffer_mode() == 0 ) - result = i801_block_transaction_by_block(data, read_write, - hwpec); - else - result = i801_block_transaction_byte_by_byte(data, read_write, - hwpec); - - if (result == 0 && hwpec) - i801_wait_hwpec(); - + result = 0; +END: if (command == I2C_SMBUS_I2C_BLOCK_DATA) { /* restore saved configuration register value */ pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); @@ -473,22 +393,19 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, return -1; } - if (hwpec) /* enable/disable hardware PEC */ - outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL); - else - outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); + outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */ if(block) ret = i801_block_transaction(data, read_write, size, hwpec); - else - ret = i801_transaction(xact | ENABLE_INT9); + else { + outb_p(xact | ENABLE_INT9, SMBHSTCNT); + ret = i801_transaction(); + } /* Some BIOSes don't like it when PEC is enabled at reboot or resume - time, so we forcibly disable it after every transaction. Turn off - E32B for the same reason. */ + time, so we forcibly disable it after every transaction. */ if (hwpec) - outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), - SMBAUXCTL); + outb_p(0, SMBAUXCTL); if(block) return ret; diff --git a/trunk/drivers/i2c/busses/i2c-iop3xx.c b/trunk/drivers/i2c/busses/i2c-iop3xx.c index 440342bc62e1..90e2d9350c1b 100644 --- a/trunk/drivers/i2c/busses/i2c-iop3xx.c +++ b/trunk/drivers/i2c/busses/i2c-iop3xx.c @@ -491,7 +491,6 @@ iop3xx_i2c_probe(struct platform_device *pdev) new_adapter->id = I2C_HW_IOP3XX; new_adapter->owner = THIS_MODULE; new_adapter->dev.parent = &pdev->dev; - new_adapter->nr = pdev->id; /* * Default values...should these come in from board code? @@ -509,7 +508,7 @@ iop3xx_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, new_adapter); new_adapter->algo_data = adapter_data; - i2c_add_numbered_adapter(new_adapter); + i2c_add_adapter(new_adapter); return 0; diff --git a/trunk/drivers/i2c/busses/i2c-mpc.c b/trunk/drivers/i2c/busses/i2c-mpc.c index 851c3ed513d0..c6b6898592b1 100644 --- a/trunk/drivers/i2c/busses/i2c-mpc.c +++ b/trunk/drivers/i2c/busses/i2c-mpc.c @@ -74,25 +74,6 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) return IRQ_HANDLED; } -/* Sometimes 9th clock pulse isn't generated, and slave doesn't release - * the bus, because it wants to send ACK. - * Following sequence of enabling/disabling and sending start/stop generates - * the pulse, so it's all OK. - */ -static void mpc_i2c_fixup(struct mpc_i2c *i2c) -{ - writeccr(i2c, 0); - udelay(30); - writeccr(i2c, CCR_MEN); - udelay(30); - writeccr(i2c, CCR_MSTA | CCR_MTX); - udelay(30); - writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); - udelay(30); - writeccr(i2c, CCR_MEN); - udelay(30); -} - static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) { unsigned long orig_jiffies = jiffies; @@ -172,7 +153,6 @@ static void mpc_i2c_start(struct mpc_i2c *i2c) static void mpc_i2c_stop(struct mpc_i2c *i2c) { writeccr(i2c, CCR_MEN); - writeccr(i2c, 0); } static int mpc_write(struct mpc_i2c *i2c, int target, @@ -265,9 +245,6 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) } if (time_after(jiffies, orig_jiffies + HZ)) { pr_debug("I2C: timeout\n"); - if (readb(i2c->base + MPC_I2C_SR) == - (CSR_MCF | CSR_MBB | CSR_RXAK)) - mpc_i2c_fixup(i2c); return -EIO; } schedule(); @@ -350,10 +327,9 @@ static int fsl_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2c); i2c->adap = mpc_ops; - i2c->adap.nr = pdev->id; i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &pdev->dev; - if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) { + if ((result = i2c_add_adapter(&i2c->adap)) < 0) { printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); goto fail_add; } diff --git a/trunk/drivers/i2c/busses/i2c-mv64xxx.c b/trunk/drivers/i2c/busses/i2c-mv64xxx.c index 251154ae5d97..a55b3335d1be 100644 --- a/trunk/drivers/i2c/busses/i2c-mv64xxx.c +++ b/trunk/drivers/i2c/busses/i2c-mv64xxx.c @@ -527,7 +527,6 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->adapter.class = I2C_CLASS_HWMON; drv_data->adapter.timeout = pdata->timeout; drv_data->adapter.retries = pdata->retries; - drv_data->adapter.nr = pd->id; platform_set_drvdata(pd, drv_data); i2c_set_adapdata(&drv_data->adapter, drv_data); @@ -540,7 +539,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->irq); rc = -EINVAL; goto exit_unmap_regs; - } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { + } else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) { dev_err(&drv_data->adapter.dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); goto exit_free_irq; diff --git a/trunk/drivers/i2c/busses/i2c-nforce2.c b/trunk/drivers/i2c/busses/i2c-nforce2.c index c48140f782d0..3cd0d63e7b50 100644 --- a/trunk/drivers/i2c/busses/i2c-nforce2.c +++ b/trunk/drivers/i2c/busses/i2c-nforce2.c @@ -61,7 +61,6 @@ struct nforce2_smbus { struct i2c_adapter adapter; int base; int size; - int blockops; }; @@ -81,8 +80,6 @@ struct nforce2_smbus { #define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */ #define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */ #define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */ -#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data - bytes */ #define NVIDIA_SMB_STS_DONE 0x80 #define NVIDIA_SMB_STS_ALRM 0x40 @@ -95,7 +92,6 @@ struct nforce2_smbus { #define NVIDIA_SMB_PRTCL_BYTE 0x04 #define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06 #define NVIDIA_SMB_PRTCL_WORD_DATA 0x08 -#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a #define NVIDIA_SMB_PRTCL_PEC 0x80 static struct pci_driver nforce2_driver; @@ -107,8 +103,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, { struct nforce2_smbus *smbus = adap->algo_data; unsigned char protocol, pec, temp; - u8 len; - int i; protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : NVIDIA_SMB_PRTCL_WRITE; @@ -143,25 +137,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec; break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) { - dev_err(&adap->dev, - "Transaction failed " - "(requested block size: %d)\n", - len); - return -1; - } - outb_p(len, NVIDIA_SMB_BCNT); - for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) - outb_p(data->block[i + 1], - NVIDIA_SMB_DATA+i); - } - protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec; - break; - default: dev_err(&adap->dev, "Unsupported transaction %d\n", size); return -1; @@ -199,14 +174,6 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, case I2C_SMBUS_WORD_DATA: data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8); break; - - case I2C_SMBUS_BLOCK_DATA: - len = inb_p(NVIDIA_SMB_BCNT); - len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); - for (i = 0; i < len; i++) - data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); - data->block[0] = len; - break; } return 0; @@ -217,9 +184,7 @@ static u32 nforce2_func(struct i2c_adapter *adapter) { /* other functionality might be possible, but is not tested */ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - (((struct nforce2_smbus*)adapter->algo_data)->blockops ? - I2C_FUNC_SMBUS_BLOCK_DATA : 0); + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA; } static struct i2c_algorithm smbus_algorithm = { @@ -303,13 +268,6 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ return -ENOMEM; pci_set_drvdata(dev, smbuses); - switch(dev->device) { - case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS: - case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS: - smbuses[0].blockops = 1; - smbuses[1].blockops = 1; - } - /* SMBus adapter 1 */ res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); if (res1 < 0) { diff --git a/trunk/drivers/i2c/busses/i2c-piix4.c b/trunk/drivers/i2c/busses/i2c-piix4.c index debc76cd2161..5a52bf5e3fb0 100644 --- a/trunk/drivers/i2c/busses/i2c-piix4.c +++ b/trunk/drivers/i2c/busses/i2c-piix4.c @@ -23,7 +23,7 @@ Supports: Intel PIIX4, 440MX Serverworks OSB4, CSB5, CSB6, HT-1000 - ATI IXP200, IXP300, IXP400, SB600, SB700 + ATI IXP200, IXP300, IXP400, SB600 SMSC Victory66 Note: we assume there can only be one device, with one SMBus interface. @@ -399,8 +399,6 @@ static struct pci_device_id piix4_ids[] = { .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SMBUS), .driver_data = 0 }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SMBUS), - .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), diff --git a/trunk/drivers/i2c/busses/i2c-pmcmsp.c b/trunk/drivers/i2c/busses/i2c-pmcmsp.c deleted file mode 100644 index 03188d277af1..000000000000 --- a/trunk/drivers/i2c/busses/i2c-pmcmsp.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Specific bus support for PMC-TWI compliant implementation on MSP71xx. - * - * Copyright 2005-2007 PMC-Sierra, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "pmcmsptwi" - -#define MSP_TWI_SF_CLK_REG_OFFSET 0x00 -#define MSP_TWI_HS_CLK_REG_OFFSET 0x04 -#define MSP_TWI_CFG_REG_OFFSET 0x08 -#define MSP_TWI_CMD_REG_OFFSET 0x0c -#define MSP_TWI_ADD_REG_OFFSET 0x10 -#define MSP_TWI_DAT_0_REG_OFFSET 0x14 -#define MSP_TWI_DAT_1_REG_OFFSET 0x18 -#define MSP_TWI_INT_STS_REG_OFFSET 0x1c -#define MSP_TWI_INT_MSK_REG_OFFSET 0x20 -#define MSP_TWI_BUSY_REG_OFFSET 0x24 - -#define MSP_TWI_INT_STS_DONE (1 << 0) -#define MSP_TWI_INT_STS_LOST_ARBITRATION (1 << 1) -#define MSP_TWI_INT_STS_NO_RESPONSE (1 << 2) -#define MSP_TWI_INT_STS_DATA_COLLISION (1 << 3) -#define MSP_TWI_INT_STS_BUSY (1 << 4) -#define MSP_TWI_INT_STS_ALL 0x1f - -#define MSP_MAX_BYTES_PER_RW 8 -#define MSP_MAX_POLL 5 -#define MSP_POLL_DELAY 10 -#define MSP_IRQ_TIMEOUT (MSP_MAX_POLL * MSP_POLL_DELAY) - -/* IO Operation macros */ -#define pmcmsptwi_readl __raw_readl -#define pmcmsptwi_writel __raw_writel - -/* TWI command type */ -enum pmcmsptwi_cmd_type { - MSP_TWI_CMD_WRITE = 0, /* Write only */ - MSP_TWI_CMD_READ = 1, /* Read only */ - MSP_TWI_CMD_WRITE_READ = 2, /* Write then Read */ -}; - -/* The possible results of the xferCmd */ -enum pmcmsptwi_xfer_result { - MSP_TWI_XFER_OK = 0, - MSP_TWI_XFER_TIMEOUT, - MSP_TWI_XFER_BUSY, - MSP_TWI_XFER_DATA_COLLISION, - MSP_TWI_XFER_NO_RESPONSE, - MSP_TWI_XFER_LOST_ARBITRATION, -}; - -/* Corresponds to a PMCTWI clock configuration register */ -struct pmcmsptwi_clock { - u8 filter; /* Bits 15:12, default = 0x03 */ - u16 clock; /* Bits 9:0, default = 0x001f */ -}; - -struct pmcmsptwi_clockcfg { - struct pmcmsptwi_clock standard; /* The standard/fast clock config */ - struct pmcmsptwi_clock highspeed; /* The highspeed clock config */ -}; - -/* Corresponds to the main TWI configuration register */ -struct pmcmsptwi_cfg { - u8 arbf; /* Bits 15:12, default=0x03 */ - u8 nak; /* Bits 11:8, default=0x03 */ - u8 add10; /* Bit 7, default=0x00 */ - u8 mst_code; /* Bits 6:4, default=0x00 */ - u8 arb; /* Bit 1, default=0x01 */ - u8 highspeed; /* Bit 0, default=0x00 */ -}; - -/* A single pmctwi command to issue */ -struct pmcmsptwi_cmd { - u16 addr; /* The slave address (7 or 10 bits) */ - enum pmcmsptwi_cmd_type type; /* The command type */ - u8 write_len; /* Number of bytes in the write buffer */ - u8 read_len; /* Number of bytes in the read buffer */ - u8 *write_data; /* Buffer of characters to send */ - u8 *read_data; /* Buffer to fill with incoming data */ -}; - -/* The private data */ -struct pmcmsptwi_data { - void __iomem *iobase; /* iomapped base for IO */ - int irq; /* IRQ to use (0 disables) */ - struct completion wait; /* Completion for xfer */ - struct mutex lock; /* Used for threadsafeness */ - enum pmcmsptwi_xfer_result last_result; /* result of last xfer */ -}; - -/* The default settings */ -const static struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = { - .standard = { - .filter = 0x3, - .clock = 0x1f, - }, - .highspeed = { - .filter = 0x3, - .clock = 0x1f, - }, -}; - -const static struct pmcmsptwi_cfg pmcmsptwi_defcfg = { - .arbf = 0x03, - .nak = 0x03, - .add10 = 0x00, - .mst_code = 0x00, - .arb = 0x01, - .highspeed = 0x00, -}; - -static struct pmcmsptwi_data pmcmsptwi_data; - -static struct i2c_adapter pmcmsptwi_adapter; - -/* inline helper functions */ -static inline u32 pmcmsptwi_clock_to_reg( - const struct pmcmsptwi_clock *clock) -{ - return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff); -} - -static inline void pmcmsptwi_reg_to_clock( - u32 reg, struct pmcmsptwi_clock *clock) -{ - clock->filter = (reg >> 12) & 0xf; - clock->clock = reg & 0x03ff; -} - -static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg) -{ - return ((cfg->arbf & 0xf) << 12) | - ((cfg->nak & 0xf) << 8) | - ((cfg->add10 & 0x1) << 7) | - ((cfg->mst_code & 0x7) << 4) | - ((cfg->arb & 0x1) << 1) | - (cfg->highspeed & 0x1); -} - -static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg) -{ - cfg->arbf = (reg >> 12) & 0xf; - cfg->nak = (reg >> 8) & 0xf; - cfg->add10 = (reg >> 7) & 0x1; - cfg->mst_code = (reg >> 4) & 0x7; - cfg->arb = (reg >> 1) & 0x1; - cfg->highspeed = reg & 0x1; -} - -/* - * Sets the current clock configuration - */ -static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg, - struct pmcmsptwi_data *data) -{ - mutex_lock(&data->lock); - pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard), - data->iobase + MSP_TWI_SF_CLK_REG_OFFSET); - pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed), - data->iobase + MSP_TWI_HS_CLK_REG_OFFSET); - mutex_unlock(&data->lock); -} - -/* - * Gets the current TWI bus configuration - */ -static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg, - struct pmcmsptwi_data *data) -{ - mutex_lock(&data->lock); - pmcmsptwi_reg_to_cfg(pmcmsptwi_readl( - data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg); - mutex_unlock(&data->lock); -} - -/* - * Sets the current TWI bus configuration - */ -static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg, - struct pmcmsptwi_data *data) -{ - mutex_lock(&data->lock); - pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg), - data->iobase + MSP_TWI_CFG_REG_OFFSET); - mutex_unlock(&data->lock); -} - -/* - * Parses the 'int_sts' register and returns a well-defined error code - */ -static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg) -{ - if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: Lost arbitration\n"); - return MSP_TWI_XFER_LOST_ARBITRATION; - } else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: No response\n"); - return MSP_TWI_XFER_NO_RESPONSE; - } else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: Data collision\n"); - return MSP_TWI_XFER_DATA_COLLISION; - } else if (reg & MSP_TWI_INT_STS_BUSY) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: Bus busy\n"); - return MSP_TWI_XFER_BUSY; - } - - dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n"); - return MSP_TWI_XFER_OK; -} - -/* - * In interrupt mode, handle the interrupt. - * NOTE: Assumes data->lock is held. - */ -static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr) -{ - struct pmcmsptwi_data *data = ptr; - - u32 reason = pmcmsptwi_readl(data->iobase + - MSP_TWI_INT_STS_REG_OFFSET); - pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET); - - dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason); - if (!(reason & MSP_TWI_INT_STS_DONE)) - return IRQ_NONE; - - data->last_result = pmcmsptwi_get_result(reason); - complete(&data->wait); - - return IRQ_HANDLED; -} - -/* - * Probe for and register the device and return 0 if there is one. - */ -static int __devinit pmcmsptwi_probe(struct platform_device *pldev) -{ - struct resource *res; - int rc = -ENODEV; - - /* get the static platform resources */ - res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pldev->dev, "IOMEM resource not found\n"); - goto ret_err; - } - - /* reserve the memory region */ - if (!request_mem_region(res->start, res->end - res->start + 1, - pldev->name)) { - dev_err(&pldev->dev, - "Unable to get memory/io address region 0x%08x\n", - res->start); - rc = -EBUSY; - goto ret_err; - } - - /* remap the memory */ - pmcmsptwi_data.iobase = ioremap_nocache(res->start, - res->end - res->start + 1); - if (!pmcmsptwi_data.iobase) { - dev_err(&pldev->dev, - "Unable to ioremap address 0x%08x\n", res->start); - rc = -EIO; - goto ret_unreserve; - } - - /* request the irq */ - pmcmsptwi_data.irq = platform_get_irq(pldev, 0); - if (pmcmsptwi_data.irq) { - rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt, - IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, - pldev->name, &pmcmsptwi_data); - if (rc == 0) { - /* - * Enable 'DONE' interrupt only. - * - * If you enable all interrupts, you will get one on - * error and another when the operation completes. - * This way you only have to handle one interrupt, - * but you can still check all result flags. - */ - pmcmsptwi_writel(MSP_TWI_INT_STS_DONE, - pmcmsptwi_data.iobase + - MSP_TWI_INT_MSK_REG_OFFSET); - } else { - dev_warn(&pldev->dev, - "Could not assign TWI IRQ handler " - "to irq %d (continuing with poll)\n", - pmcmsptwi_data.irq); - pmcmsptwi_data.irq = 0; - } - } - - init_completion(&pmcmsptwi_data.wait); - mutex_init(&pmcmsptwi_data.lock); - - pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data); - pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data); - - printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n"); - - pmcmsptwi_adapter.dev.parent = &pldev->dev; - platform_set_drvdata(pldev, &pmcmsptwi_adapter); - i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data); - - rc = i2c_add_adapter(&pmcmsptwi_adapter); - if (rc) { - dev_err(&pldev->dev, "Unable to register I2C adapter\n"); - goto ret_unmap; - } - - return 0; - -ret_unmap: - platform_set_drvdata(pldev, NULL); - if (pmcmsptwi_data.irq) { - pmcmsptwi_writel(0, - pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET); - free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data); - } - - iounmap(pmcmsptwi_data.iobase); - -ret_unreserve: - release_mem_region(res->start, res->end - res->start + 1); - -ret_err: - return rc; -} - -/* - * Release the device and return 0 if there is one. - */ -static int __devexit pmcmsptwi_remove(struct platform_device *pldev) -{ - struct resource *res; - - i2c_del_adapter(&pmcmsptwi_adapter); - - platform_set_drvdata(pldev, NULL); - if (pmcmsptwi_data.irq) { - pmcmsptwi_writel(0, - pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET); - free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data); - } - - iounmap(pmcmsptwi_data.iobase); - - res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); - - return 0; -} - -/* - * Polls the 'busy' register until the command is complete. - * NOTE: Assumes data->lock is held. - */ -static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data) -{ - int i; - - for (i = 0; i < MSP_MAX_POLL; i++) { - u32 val = pmcmsptwi_readl(data->iobase + - MSP_TWI_BUSY_REG_OFFSET); - if (val == 0) { - u32 reason = pmcmsptwi_readl(data->iobase + - MSP_TWI_INT_STS_REG_OFFSET); - pmcmsptwi_writel(reason, data->iobase + - MSP_TWI_INT_STS_REG_OFFSET); - data->last_result = pmcmsptwi_get_result(reason); - return; - } - udelay(MSP_POLL_DELAY); - } - - dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n"); - data->last_result = MSP_TWI_XFER_TIMEOUT; -} - -/* - * Do the transfer (low level): - * May use interrupt-driven or polling, depending on if an IRQ is - * presently registered. - * NOTE: Assumes data->lock is held. - */ -static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer( - u32 reg, struct pmcmsptwi_data *data) -{ - dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg); - pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET); - if (data->irq) { - unsigned long timeleft = wait_for_completion_timeout( - &data->wait, MSP_IRQ_TIMEOUT); - if (timeleft == 0) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: IRQ timeout\n"); - complete(&data->wait); - data->last_result = MSP_TWI_XFER_TIMEOUT; - } - } else - pmcmsptwi_poll_complete(data); - - return data->last_result; -} - -/* - * Helper routine, converts 'pmctwi_cmd' struct to register format - */ -static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd) -{ - return ((cmd->type & 0x3) << 8) | - (((cmd->write_len - 1) & 0x7) << 4) | - ((cmd->read_len - 1) & 0x7); -} - -/* - * Do the transfer (high level) - */ -static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd( - struct pmcmsptwi_cmd *cmd, - struct pmcmsptwi_data *data) -{ - enum pmcmsptwi_xfer_result retval; - - if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) || - (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) || - (cmd->type == MSP_TWI_CMD_WRITE_READ && - (cmd->read_len == 0 || cmd->write_len == 0))) { - dev_err(&pmcmsptwi_adapter.dev, - "%s: Cannot transfer less than 1 byte\n", - __FUNCTION__); - return -EINVAL; - } - - if (cmd->read_len > MSP_MAX_BYTES_PER_RW || - cmd->write_len > MSP_MAX_BYTES_PER_RW) { - dev_err(&pmcmsptwi_adapter.dev, - "%s: Cannot transfer more than %d bytes\n", - __FUNCTION__, MSP_MAX_BYTES_PER_RW); - return -EINVAL; - } - - mutex_lock(&data->lock); - dev_dbg(&pmcmsptwi_adapter.dev, - "Setting address to 0x%04x\n", cmd->addr); - pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET); - - if (cmd->type == MSP_TWI_CMD_WRITE || - cmd->type == MSP_TWI_CMD_WRITE_READ) { - __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data); - tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8; - dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp); - pmcmsptwi_writel(tmp & 0x00000000ffffffffLL, - data->iobase + MSP_TWI_DAT_0_REG_OFFSET); - if (cmd->write_len > 4) - pmcmsptwi_writel(tmp >> 32, - data->iobase + MSP_TWI_DAT_1_REG_OFFSET); - } - - retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data); - if (retval != MSP_TWI_XFER_OK) - goto xfer_err; - - if (cmd->type == MSP_TWI_CMD_READ || - cmd->type == MSP_TWI_CMD_WRITE_READ) { - int i; - u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8)); - u64 tmp = (u64)pmcmsptwi_readl(data->iobase + - MSP_TWI_DAT_0_REG_OFFSET); - if (cmd->read_len > 4) - tmp |= (u64)pmcmsptwi_readl(data->iobase + - MSP_TWI_DAT_1_REG_OFFSET) << 32; - tmp &= rmsk; - dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp); - - for (i = 0; i < cmd->read_len; i++) - cmd->read_data[i] = tmp >> i; - } - -xfer_err: - mutex_unlock(&data->lock); - - return retval; -} - -/* -- Algorithm functions -- */ - -/* - * Sends an i2c command out on the adapter - */ -static int pmcmsptwi_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msg, int num) -{ - struct pmcmsptwi_data *data = i2c_get_adapdata(adap); - struct pmcmsptwi_cmd cmd; - struct pmcmsptwi_cfg oldcfg, newcfg; - int ret; - - if (num > 2) { - dev_dbg(&adap->dev, "%d messages unsupported\n", num); - return -EINVAL; - } else if (num == 2) { - /* Check for a dual write-then-read command */ - struct i2c_msg *nextmsg = msg + 1; - if (!(msg->flags & I2C_M_RD) && - (nextmsg->flags & I2C_M_RD) && - msg->addr == nextmsg->addr) { - cmd.type = MSP_TWI_CMD_WRITE_READ; - cmd.write_len = msg->len; - cmd.write_data = msg->buf; - cmd.read_len = nextmsg->len; - cmd.read_data = nextmsg->buf; - } else { - dev_dbg(&adap->dev, - "Non write-read dual messages unsupported\n"); - return -EINVAL; - } - } else if (msg->flags & I2C_M_RD) { - cmd.type = MSP_TWI_CMD_READ; - cmd.read_len = msg->len; - cmd.read_data = msg->buf; - cmd.write_len = 0; - cmd.write_data = NULL; - } else { - cmd.type = MSP_TWI_CMD_WRITE; - cmd.read_len = 0; - cmd.read_data = NULL; - cmd.write_len = msg->len; - cmd.write_data = msg->buf; - } - - if (msg->len == 0) { - dev_err(&adap->dev, "Zero-byte messages unsupported\n"); - return -EINVAL; - } - - cmd.addr = msg->addr; - - if (msg->flags & I2C_M_TEN) { - pmcmsptwi_get_twi_config(&newcfg, data); - memcpy(&oldcfg, &newcfg, sizeof(oldcfg)); - - /* Set the special 10-bit address flag */ - newcfg.add10 = 1; - - pmcmsptwi_set_twi_config(&newcfg, data); - } - - /* Execute the command */ - ret = pmcmsptwi_xfer_cmd(&cmd, data); - - if (msg->flags & I2C_M_TEN) - pmcmsptwi_set_twi_config(&oldcfg, data); - - dev_dbg(&adap->dev, "I2C %s of %d bytes ", - (msg->flags & I2C_M_RD) ? "read" : "write", msg->len); - if (ret != MSP_TWI_XFER_OK) { - /* - * TODO: We could potentially loop and retry in the case - * of MSP_TWI_XFER_TIMEOUT. - */ - dev_dbg(&adap->dev, "failed\n"); - return -1; - } - - dev_dbg(&adap->dev, "succeeded\n"); - return 0; -} - -static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL; -} - -/* -- Initialization -- */ - -static struct i2c_algorithm pmcmsptwi_algo = { - .master_xfer = pmcmsptwi_master_xfer, - .functionality = pmcmsptwi_i2c_func, -}; - -static struct i2c_adapter pmcmsptwi_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON, - .algo = &pmcmsptwi_algo, - .name = DRV_NAME, -}; - -static struct platform_driver pmcmsptwi_driver = { - .probe = pmcmsptwi_probe, - .remove = __devexit_p(pmcmsptwi_remove), - .driver { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init pmcmsptwi_init(void) -{ - return platform_driver_register(&pmcmsptwi_driver); -} - -static void __exit pmcmsptwi_exit(void) -{ - platform_driver_unregister(&pmcmsptwi_driver); -} - -MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver"); -MODULE_LICENSE("GPL"); - -module_init(pmcmsptwi_init); -module_exit(pmcmsptwi_exit); diff --git a/trunk/drivers/i2c/busses/i2c-powermac.c b/trunk/drivers/i2c/busses/i2c-powermac.c index 0ab4f2627c26..1425d2245c82 100644 --- a/trunk/drivers/i2c/busses/i2c-powermac.c +++ b/trunk/drivers/i2c/busses/i2c-powermac.c @@ -121,7 +121,8 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, if (rc) goto bail; rc = pmac_i2c_xfer(bus, addrdir, 1, command, - &data->block[1], data->block[0]); + read ? data->block : &data->block[1], + data->block[0]); break; default: diff --git a/trunk/drivers/i2c/busses/i2c-pxa.c b/trunk/drivers/i2c/busses/i2c-pxa.c index 9d6b790d4321..28e7b91a4553 100644 --- a/trunk/drivers/i2c/busses/i2c-pxa.c +++ b/trunk/drivers/i2c/busses/i2c-pxa.c @@ -921,14 +921,7 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->adap.class = plat->class; } - /* - * If "dev->id" is negative we consider it as zero. - * The reason to do so is to avoid sysfs names that only make - * sense when there are multiple adapters. - */ - i2c->adap.nr = dev->id >= 0 ? dev->id : 0; - - ret = i2c_add_numbered_adapter(&i2c->adap); + ret = i2c_add_adapter(&i2c->adap); if (ret < 0) { printk(KERN_INFO "I2C: Failed to add bus\n"); goto eadapt; diff --git a/trunk/drivers/i2c/busses/i2c-rpx.c b/trunk/drivers/i2c/busses/i2c-rpx.c new file mode 100644 index 000000000000..8764df06f51d --- /dev/null +++ b/trunk/drivers/i2c/busses/i2c-rpx.c @@ -0,0 +1,101 @@ +/* + * Embedded Planet RPX Lite MPC8xx CPM I2C interface. + * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). + * + * moved into proper i2c interface; + * Brad Parker (brad@heeltoe.com) + * + * RPX lite specific parts of the i2c interface + * Update: There actually isn't anything RPXLite-specific about this module. + * This should work for most any 8xx board. The console messages have been + * changed to eliminate RPXLite references. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +static void +rpx_iic_init(struct i2c_algo_8xx_data *data) +{ + volatile cpm8xx_t *cp; + volatile immap_t *immap; + + cp = cpmp; /* Get pointer to Communication Processor */ + immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ + + data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; + + /* Check for and use a microcode relocation patch. + */ + if ((data->reloc = data->iip->iic_rpbase)) + data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase]; + + data->i2c = (i2c8xx_t *)&(immap->im_i2c); + data->cp = cp; + + /* Initialize Port B IIC pins. + */ + cp->cp_pbpar |= 0x00000030; + cp->cp_pbdir |= 0x00000030; + cp->cp_pbodr |= 0x00000030; + + /* Allocate space for two transmit and two receive buffer + * descriptors in the DP ram. + */ + data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8); + + /* ptr to i2c area */ + data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c); +} + +static int rpx_install_isr(int irq, void (*func)(void *), void *data) +{ + /* install interrupt handler */ + cpm_install_handler(irq, func, data); + + return 0; +} + +static struct i2c_algo_8xx_data rpx_data = { + .setisr = rpx_install_isr +}; + +static struct i2c_adapter rpx_ops = { + .owner = THIS_MODULE, + .name = "m8xx", + .id = I2C_HW_MPC8XX_EPON, + .algo_data = &rpx_data, +}; + +int __init i2c_rpx_init(void) +{ + printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n"); + + /* reset hardware to sane state */ + rpx_iic_init(&rpx_data); + + if (i2c_8xx_add_bus(&rpx_ops) < 0) { + printk(KERN_ERR "i2c-rpx: Unable to register with I2C\n"); + return -ENODEV; + } + + return 0; +} + +void __exit i2c_rpx_exit(void) +{ + i2c_8xx_del_bus(&rpx_ops); +} + +MODULE_AUTHOR("Dan Malek "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards"); + +module_init(i2c_rpx_init); +module_exit(i2c_rpx_exit); diff --git a/trunk/drivers/i2c/busses/i2c-savage4.c b/trunk/drivers/i2c/busses/i2c-savage4.c index 8adf4abaa035..b7fb65c30112 100644 --- a/trunk/drivers/i2c/busses/i2c-savage4.c +++ b/trunk/drivers/i2c/busses/i2c-savage4.c @@ -25,6 +25,8 @@ /* This interfaces to the I2C bus of the Savage4 to gain access to the BT869 and possibly other I2C devices. The DDC bus is not yet supported because its register is not memory-mapped. + However we leave the DDC code here, commented out, to make + it easier to add later. */ #include @@ -35,19 +37,36 @@ #include #include -/* device IDs */ +/* 3DFX defines */ +#define PCI_CHIP_SAVAGE3D 0x8A20 +#define PCI_CHIP_SAVAGE3D_MV 0x8A21 #define PCI_CHIP_SAVAGE4 0x8A22 #define PCI_CHIP_SAVAGE2000 0x9102 +#define PCI_CHIP_PROSAVAGE_PM 0x8A25 +#define PCI_CHIP_PROSAVAGE_KM 0x8A26 +#define PCI_CHIP_SAVAGE_MX_MV 0x8c10 +#define PCI_CHIP_SAVAGE_MX 0x8c11 +#define PCI_CHIP_SAVAGE_IX_MV 0x8c12 +#define PCI_CHIP_SAVAGE_IX 0x8c13 #define REG 0xff20 /* Serial Port 1 Register */ /* bit locations in the register */ +#define DDC_ENAB 0x00040000 +#define DDC_SCL_OUT 0x00080000 +#define DDC_SDA_OUT 0x00100000 +#define DDC_SCL_IN 0x00200000 +#define DDC_SDA_IN 0x00400000 #define I2C_ENAB 0x00000020 #define I2C_SCL_OUT 0x00000001 #define I2C_SDA_OUT 0x00000002 #define I2C_SCL_IN 0x00000008 #define I2C_SDA_IN 0x00000010 +/* initialization states */ +#define INIT2 0x20 +#define INIT3 0x04 + /* delays */ #define CYCLE_DELAY 10 #define TIMEOUT (HZ / 2) diff --git a/trunk/drivers/i2c/busses/i2c-sis5595.c b/trunk/drivers/i2c/busses/i2c-sis5595.c index 283769cecee2..a6feed449dbe 100644 --- a/trunk/drivers/i2c/busses/i2c-sis5595.c +++ b/trunk/drivers/i2c/busses/i2c-sis5595.c @@ -129,7 +129,6 @@ MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller" static struct pci_driver sis5595_driver; static unsigned short sis5595_base; -static struct pci_dev *sis5595_pdev; static u8 sis5595_read(u8 reg) { @@ -380,8 +379,6 @@ MODULE_DEVICE_TABLE (pci, sis5595_ids); static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int err; - if (sis5595_setup(dev)) { dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n"); return -ENODEV; @@ -392,24 +389,20 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_ sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX); - err = i2c_add_adapter(&sis5595_adapter); - if (err) { - release_region(sis5595_base + SMB_INDEX, 2); - return err; - } + return i2c_add_adapter(&sis5595_adapter); +} - /* Always return failure here. This is to allow other drivers to bind - * to this pci device. We don't really want to have control over the - * pci device, we only wanted to read as few register values from it. - */ - sis5595_pdev = pci_dev_get(dev); - return -ENODEV; +static void __devexit sis5595_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&sis5595_adapter); + release_region(sis5595_base + SMB_INDEX, 2); } static struct pci_driver sis5595_driver = { .name = "sis5595_smbus", .id_table = sis5595_ids, .probe = sis5595_probe, + .remove = __devexit_p(sis5595_remove), }; static int __init i2c_sis5595_init(void) @@ -420,12 +413,6 @@ static int __init i2c_sis5595_init(void) static void __exit i2c_sis5595_exit(void) { pci_unregister_driver(&sis5595_driver); - if (sis5595_pdev) { - i2c_del_adapter(&sis5595_adapter); - release_region(sis5595_base + SMB_INDEX, 2); - pci_dev_put(sis5595_pdev); - sis5595_pdev = NULL; - } } MODULE_AUTHOR("Frodo Looijaard "); diff --git a/trunk/drivers/i2c/busses/i2c-taos-evm.c b/trunk/drivers/i2c/busses/i2c-taos-evm.c deleted file mode 100644 index 1b0cfd5472fd..000000000000 --- a/trunk/drivers/i2c/busses/i2c-taos-evm.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Driver for the TAOS evaluation modules - * These devices include an I2C master which can be controlled over the - * serial port. - * - * Copyright (C) 2007 Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAOS_BUFFER_SIZE 63 - -#define TAOS_STATE_INIT 0 -#define TAOS_STATE_IDLE 1 -#define TAOS_STATE_SEND 2 -#define TAOS_STATE_RECV 3 - -#define TAOS_CMD_RESET 0x12 - -static DECLARE_WAIT_QUEUE_HEAD(wq); - -struct taos_data { - struct i2c_adapter adapter; - struct i2c_client *client; - int state; - u8 addr; /* last used address */ - unsigned char buffer[TAOS_BUFFER_SIZE]; - unsigned int pos; /* position inside the buffer */ -}; - -/* TAOS TSL2550 EVM */ -static struct i2c_board_info tsl2550_info = { - I2C_BOARD_INFO("tsl2550", 0x39), - .type = "tsl2550", -}; - -/* Instantiate i2c devices based on the adapter name */ -static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter) -{ - if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) { - dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n", - tsl2550_info.driver_name, tsl2550_info.addr); - return i2c_new_device(adapter, &tsl2550_info); - } - - return NULL; -} - -static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - struct serio *serio = adapter->algo_data; - struct taos_data *taos = serio_get_drvdata(serio); - char *p; - - /* Encode our transaction. "@" is for the device address, "$" for the - SMBus command and "#" for the data. */ - p = taos->buffer; - - /* The device remembers the last used address, no need to send it - again if it's the same */ - if (addr != taos->addr) - p += sprintf(p, "@%02X", addr); - - switch (size) { - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - sprintf(p, "$#%02X", command); - else - sprintf(p, "$"); - break; - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_WRITE) - sprintf(p, "$%02X#%02X", command, data->byte); - else - sprintf(p, "$%02X", command); - break; - default: - dev_dbg(&adapter->dev, "Unsupported transaction size %d\n", - size); - return -EINVAL; - } - - /* Send the transaction to the TAOS EVM */ - dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer); - taos->pos = 0; - taos->state = TAOS_STATE_SEND; - serio_write(serio, taos->buffer[0]); - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(250)); - if (taos->state != TAOS_STATE_IDLE) { - dev_err(&adapter->dev, "Transaction failed " - "(state=%d, pos=%d)\n", taos->state, taos->pos); - taos->addr = 0; - return -EIO; - } - taos->addr = addr; - - /* Start the transaction and read the answer */ - taos->pos = 0; - taos->state = TAOS_STATE_RECV; - serio_write(serio, read_write == I2C_SMBUS_WRITE ? '>' : '<'); - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(150)); - if (taos->state != TAOS_STATE_IDLE - || taos->pos != 6) { - dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n", - taos->pos); - return -EIO; - } - dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer); - - /* Interpret the returned string */ - p = taos->buffer + 2; - p[3] = '\0'; - if (!strcmp(p, "NAK")) - return -ENODEV; - - if (read_write == I2C_SMBUS_WRITE) { - if (!strcmp(p, "ACK")) - return 0; - } else { - if (p[0] == 'x') { - data->byte = simple_strtol(p + 1, NULL, 16); - return 0; - } - } - - return -EIO; -} - -static u32 taos_smbus_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA; -} - -static const struct i2c_algorithm taos_algorithm = { - .smbus_xfer = taos_smbus_xfer, - .functionality = taos_smbus_func, -}; - -static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) -{ - struct taos_data *taos = serio_get_drvdata(serio); - - switch (taos->state) { - case TAOS_STATE_INIT: - taos->buffer[taos->pos++] = data; - if (data == ':' - || taos->pos == TAOS_BUFFER_SIZE - 1) { - taos->buffer[taos->pos] = '\0'; - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); - } - break; - case TAOS_STATE_SEND: - if (taos->buffer[++taos->pos]) - serio_write(serio, taos->buffer[taos->pos]); - else { - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); - } - break; - case TAOS_STATE_RECV: - taos->buffer[taos->pos++] = data; - if (data == ']') { - taos->buffer[taos->pos] = '\0'; - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); - } - break; - } - - return IRQ_HANDLED; -} - -/* Extract the adapter name from the buffer received after reset. - The buffer is modified and a pointer inside the buffer is returned. */ -static char *taos_adapter_name(char *buffer) -{ - char *start, *end; - - start = strstr(buffer, "TAOS "); - if (!start) - return NULL; - - end = strchr(start, '\r'); - if (!end) - return NULL; - *end = '\0'; - - return start; -} - -static int taos_connect(struct serio *serio, struct serio_driver *drv) -{ - struct taos_data *taos; - struct i2c_adapter *adapter; - char *name; - int err; - - taos = kzalloc(sizeof(struct taos_data), GFP_KERNEL); - if (!taos) { - err = -ENOMEM; - goto exit; - } - taos->state = TAOS_STATE_INIT; - serio_set_drvdata(serio, taos); - - err = serio_open(serio, drv); - if (err) - goto exit_kfree; - - adapter = &taos->adapter; - adapter->owner = THIS_MODULE; - adapter->algo = &taos_algorithm; - adapter->algo_data = serio; - adapter->dev.parent = &serio->dev; - - /* Reset the TAOS evaluation module to identify it */ - serio_write(serio, TAOS_CMD_RESET); - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(2000)); - - if (taos->state != TAOS_STATE_IDLE) { - err = -ENODEV; - dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, " - "pos=%d)\n", taos->state, taos->pos); - goto exit_close; - } - - name = taos_adapter_name(taos->buffer); - if (!name) { - err = -ENODEV; - dev_err(&serio->dev, "TAOS EVM identification failed\n"); - goto exit_close; - } - strlcpy(adapter->name, name, sizeof(adapter->name)); - - err = i2c_add_adapter(adapter); - if (err) - goto exit_close; - dev_dbg(&serio->dev, "Connected to TAOS EVM\n"); - - taos->client = taos_instantiate_device(adapter); - return 0; - - exit_close: - serio_close(serio); - exit_kfree: - serio_set_drvdata(serio, NULL); - kfree(taos); - exit: - return err; -} - -static void taos_disconnect(struct serio *serio) -{ - struct taos_data *taos = serio_get_drvdata(serio); - - if (taos->client) - i2c_unregister_device(taos->client); - i2c_del_adapter(&taos->adapter); - serio_close(serio); - serio_set_drvdata(serio, NULL); - kfree(taos); - - dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n"); -} - -static struct serio_device_id taos_serio_ids[] = { - { - .type = SERIO_RS232, - .proto = SERIO_TAOSEVM, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; -MODULE_DEVICE_TABLE(serio, taos_serio_ids); - -static struct serio_driver taos_drv = { - .driver = { - .name = "taos-evm", - }, - .description = "TAOS evaluation module driver", - .id_table = taos_serio_ids, - .connect = taos_connect, - .disconnect = taos_disconnect, - .interrupt = taos_interrupt, -}; - -static int __init taos_init(void) -{ - return serio_register_driver(&taos_drv); -} - -static void __exit taos_exit(void) -{ - serio_unregister_driver(&taos_drv); -} - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("TAOS evaluation module driver"); -MODULE_LICENSE("GPL"); - -module_init(taos_init); -module_exit(taos_exit); diff --git a/trunk/drivers/i2c/busses/i2c-viapro.c b/trunk/drivers/i2c/busses/i2c-viapro.c index a0f7e4a303b5..7a2bc06304fc 100644 --- a/trunk/drivers/i2c/busses/i2c-viapro.c +++ b/trunk/drivers/i2c/busses/i2c-viapro.c @@ -235,7 +235,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, if (!(vt596_features & FEATURE_I2CBLOCK)) goto exit_unsupported; if (read_write == I2C_SMBUS_READ) - outb_p(data->block[0], SMBHSTDAT0); + outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0); /* Fall through */ case I2C_SMBUS_BLOCK_DATA: outb_p(command, SMBHSTCMD); diff --git a/trunk/drivers/i2c/busses/scx200_acb.c b/trunk/drivers/i2c/busses/scx200_acb.c index e6c4a2b762ec..0d6bd4f7b7fa 100644 --- a/trunk/drivers/i2c/busses/scx200_acb.c +++ b/trunk/drivers/i2c/busses/scx200_acb.c @@ -310,6 +310,8 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, break; case I2C_SMBUS_I2C_BLOCK_DATA: + if (rw == I2C_SMBUS_READ) + data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */ len = data->block[0]; if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) return -EINVAL; @@ -386,7 +388,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = { }; static struct scx200_acb_iface *scx200_acb_list; -static DEFINE_MUTEX(scx200_acb_list_mutex); +static DECLARE_MUTEX(scx200_acb_list_mutex); static __init int scx200_acb_probe(struct scx200_acb_iface *iface) { @@ -470,10 +472,10 @@ static int __init scx200_acb_create(struct scx200_acb_iface *iface) return -ENODEV; } - mutex_lock(&scx200_acb_list_mutex); + down(&scx200_acb_list_mutex); iface->next = scx200_acb_list; scx200_acb_list = iface; - mutex_unlock(&scx200_acb_list_mutex); + up(&scx200_acb_list_mutex); return 0; } @@ -631,10 +633,10 @@ static void __exit scx200_acb_cleanup(void) { struct scx200_acb_iface *iface; - mutex_lock(&scx200_acb_list_mutex); + down(&scx200_acb_list_mutex); while ((iface = scx200_acb_list) != NULL) { scx200_acb_list = iface->next; - mutex_unlock(&scx200_acb_list_mutex); + up(&scx200_acb_list_mutex); i2c_del_adapter(&iface->adapter); @@ -646,9 +648,9 @@ static void __exit scx200_acb_cleanup(void) release_region(iface->base, 8); kfree(iface); - mutex_lock(&scx200_acb_list_mutex); + down(&scx200_acb_list_mutex); } - mutex_unlock(&scx200_acb_list_mutex); + up(&scx200_acb_list_mutex); } module_init(scx200_acb_init); diff --git a/trunk/drivers/i2c/chips/Kconfig b/trunk/drivers/i2c/chips/Kconfig index 3944e889cb21..ea085a006ead 100644 --- a/trunk/drivers/i2c/chips/Kconfig +++ b/trunk/drivers/i2c/chips/Kconfig @@ -5,7 +5,7 @@ menu "Miscellaneous I2C Chip support" config SENSORS_DS1337 - tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)" + tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock" depends on EXPERIMENTAL help If you say yes here you get support for Dallas Semiconductor @@ -14,11 +14,8 @@ config SENSORS_DS1337 This driver can also be built as a module. If so, the module will be called ds1337. - This driver is deprecated and will be dropped soon. Use - rtc-ds1307 instead. - config SENSORS_DS1374 - tristate "Dallas DS1374 Real Time Clock (DEPRECATED)" + tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" depends on EXPERIMENTAL help If you say yes here you get support for Dallas Semiconductor @@ -27,19 +24,6 @@ config SENSORS_DS1374 This driver can also be built as a module. If so, the module will be called ds1374. - This driver is deprecated and will be dropped soon. Use - rtc-ds1374 instead. - -config DS1682 - tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" - depends on EXPERIMENTAL - help - If you say yes here you get support for Dallas Semiconductor - DS1682 Total Elapsed Time Recorder. - - This driver can also be built as a module. If so, the module - will be called ds1682. - config SENSORS_EEPROM tristate "EEPROM reader" depends on EXPERIMENTAL @@ -117,7 +101,7 @@ config TPS65010 will be called tps65010. config SENSORS_M41T00 - tristate "ST M41T00 RTC chip (DEPRECATED)" + tristate "ST M41T00 RTC chip" depends on PPC32 help If you say yes here you get support for the ST M41T00 RTC chip. @@ -125,9 +109,6 @@ config SENSORS_M41T00 This driver can also be built as a module. If so, the module will be called m41t00. - This driver is deprecated and will be dropped soon. Use - rtc-ds1307 or rtc-m41t80 instead. - config SENSORS_MAX6875 tristate "Maxim MAX6875 Power supply supervisor" depends on EXPERIMENTAL @@ -143,14 +124,4 @@ config SENSORS_MAX6875 This driver can also be built as a module. If so, the module will be called max6875. -config SENSORS_TSL2550 - tristate "Taos TSL2550 ambient light sensor" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Taos TSL2550 - ambient light sensor. - - This driver can also be built as a module. If so, the module - will be called tsl2550. - endmenu diff --git a/trunk/drivers/i2c/chips/Makefile b/trunk/drivers/i2c/chips/Makefile index d8cbeb3f4b63..779868ef2e26 100644 --- a/trunk/drivers/i2c/chips/Makefile +++ b/trunk/drivers/i2c/chips/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_SENSORS_DS1337) += ds1337.o obj-$(CONFIG_SENSORS_DS1374) += ds1374.o -obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_M41T00) += m41t00.o @@ -13,7 +12,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TPS65010) += tps65010.o -obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff --git a/trunk/drivers/i2c/chips/ds1682.c b/trunk/drivers/i2c/chips/ds1682.c deleted file mode 100644 index 25fd4676fb17..000000000000 --- a/trunk/drivers/i2c/chips/ds1682.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Dallas Semiconductor DS1682 Elapsed Time Recorder device driver - * - * Written by: Grant Likely - * - * Copyright (C) 2007 Secret Lab Technologies Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * The DS1682 elapsed timer recorder is a simple device that implements - * one elapsed time counter, one event counter, an alarm signal and 10 - * bytes of general purpose EEPROM. - * - * This driver provides access to the DS1682 counters and user data via - * the sysfs. The following attributes are added to the device node: - * elapsed_time (u32): Total elapsed event time in ms resolution - * alarm_time (u32): When elapsed time exceeds the value in alarm_time, - * then the alarm pin is asserted. - * event_count (u16): number of times the event pin has gone low. - * eeprom (u8[10]): general purpose EEPROM - * - * Counter registers and user data are both read/write unless the device - * has been write protected. This driver does not support turning off write - * protection. Once write protection is turned on, it is impossible to - * turn it off again, so I have left the feature out of this driver to avoid - * accidental enabling, but it is trivial to add write protect support. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Device registers */ -#define DS1682_REG_CONFIG 0x00 -#define DS1682_REG_ALARM 0x01 -#define DS1682_REG_ELAPSED 0x05 -#define DS1682_REG_EVT_CNTR 0x09 -#define DS1682_REG_EEPROM 0x0b -#define DS1682_REG_RESET 0x1d -#define DS1682_REG_WRITE_DISABLE 0x1e -#define DS1682_REG_WRITE_MEM_DISABLE 0x1f - -#define DS1682_EEPROM_SIZE 10 - -/* - * Generic counter attributes - */ -static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - __le32 val = 0; - int rc; - - dev_dbg(dev, "ds1682_show() called on %s\n", attr->attr.name); - - /* Read the register */ - rc = i2c_smbus_read_i2c_block_data(client, sattr->index, sattr->nr, - (u8 *) & val); - if (rc < 0) - return -EIO; - - /* Special case: the 32 bit regs are time values with 1/4s - * resolution, scale them up to milliseconds */ - if (sattr->nr == 4) - return sprintf(buf, "%llu\n", ((u64) le32_to_cpu(val)) * 250); - - /* Format the output string and return # of bytes */ - return sprintf(buf, "%li\n", (long)le32_to_cpu(val)); -} - -static ssize_t ds1682_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - char *endp; - u64 val; - __le32 val_le; - int rc; - - dev_dbg(dev, "ds1682_store() called on %s\n", attr->attr.name); - - /* Decode input */ - val = simple_strtoull(buf, &endp, 0); - if (buf == endp) { - dev_dbg(dev, "input string not a number\n"); - return -EINVAL; - } - - /* Special case: the 32 bit regs are time values with 1/4s - * resolution, scale input down to quarter-seconds */ - if (sattr->nr == 4) - do_div(val, 250); - - /* write out the value */ - val_le = cpu_to_le32(val); - rc = i2c_smbus_write_i2c_block_data(client, sattr->index, sattr->nr, - (u8 *) & val_le); - if (rc < 0) { - dev_err(dev, "register write failed; reg=0x%x, size=%i\n", - sattr->index, sattr->nr); - return -EIO; - } - - return count; -} - -/* - * Simple register attributes - */ -static SENSOR_DEVICE_ATTR_2(elapsed_time, S_IRUGO | S_IWUSR, ds1682_show, - ds1682_store, 4, DS1682_REG_ELAPSED); -static SENSOR_DEVICE_ATTR_2(alarm_time, S_IRUGO | S_IWUSR, ds1682_show, - ds1682_store, 4, DS1682_REG_ALARM); -static SENSOR_DEVICE_ATTR_2(event_count, S_IRUGO | S_IWUSR, ds1682_show, - ds1682_store, 2, DS1682_REG_EVT_CNTR); - -static const struct attribute_group ds1682_group = { - .attrs = (struct attribute *[]) { - &sensor_dev_attr_elapsed_time.dev_attr.attr, - &sensor_dev_attr_alarm_time.dev_attr.attr, - &sensor_dev_attr_event_count.dev_attr.attr, - NULL, - }, -}; - -/* - * User data attribute - */ -static ssize_t ds1682_eeprom_read(struct kobject *kobj, char *buf, loff_t off, - size_t count) -{ - struct i2c_client *client = kobj_to_i2c_client(kobj); - int rc; - - dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n", - buf, off, count); - - if (off >= DS1682_EEPROM_SIZE) - return 0; - - if (off + count > DS1682_EEPROM_SIZE) - count = DS1682_EEPROM_SIZE - off; - - rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off, - count, buf); - if (rc < 0) - return -EIO; - - return count; -} - -static ssize_t ds1682_eeprom_write(struct kobject *kobj, char *buf, loff_t off, - size_t count) -{ - struct i2c_client *client = kobj_to_i2c_client(kobj); - - dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n", - buf, off, count); - - if (off >= DS1682_EEPROM_SIZE) - return -ENOSPC; - - if (off + count > DS1682_EEPROM_SIZE) - count = DS1682_EEPROM_SIZE - off; - - /* Write out to the device */ - if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off, - count, buf) < 0) - return -EIO; - - return count; -} - -static struct bin_attribute ds1682_eeprom_attr = { - .attr = { - .name = "eeprom", - .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, - }, - .size = DS1682_EEPROM_SIZE, - .read = ds1682_eeprom_read, - .write = ds1682_eeprom_write, -}; - -/* - * Called when a ds1682 device is matched with this driver - */ -static int ds1682_probe(struct i2c_client *client) -{ - int rc; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_I2C_BLOCK)) { - dev_err(&client->dev, "i2c bus does not support the ds1682\n"); - rc = -ENODEV; - goto exit; - } - - rc = sysfs_create_group(&client->dev.kobj, &ds1682_group); - if (rc) - goto exit; - - rc = sysfs_create_bin_file(&client->dev.kobj, &ds1682_eeprom_attr); - if (rc) - goto exit_bin_attr; - - return 0; - - exit_bin_attr: - sysfs_remove_group(&client->dev.kobj, &ds1682_group); - exit: - return rc; -} - -static int ds1682_remove(struct i2c_client *client) -{ - sysfs_remove_bin_file(&client->dev.kobj, &ds1682_eeprom_attr); - sysfs_remove_group(&client->dev.kobj, &ds1682_group); - return 0; -} - -static struct i2c_driver ds1682_driver = { - .driver = { - .name = "ds1682", - }, - .probe = ds1682_probe, - .remove = ds1682_remove, -}; - -static int __init ds1682_init(void) -{ - return i2c_add_driver(&ds1682_driver); -} - -static void __exit ds1682_exit(void) -{ - i2c_del_driver(&ds1682_driver); -} - -MODULE_AUTHOR("Grant Likely "); -MODULE_DESCRIPTION("DS1682 Elapsed Time Indicator driver"); -MODULE_LICENSE("GPL"); - -module_init(ds1682_init); -module_exit(ds1682_exit); diff --git a/trunk/drivers/i2c/chips/eeprom.c b/trunk/drivers/i2c/chips/eeprom.c index 48f857ae8748..bfce13c8f1ff 100644 --- a/trunk/drivers/i2c/chips/eeprom.c +++ b/trunk/drivers/i2c/chips/eeprom.c @@ -88,10 +88,8 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice) dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - for (i = slice << 5; i < (slice + 1) << 5; i += 32) - if (i2c_smbus_read_i2c_block_data(client, i, - 32, data->data + i) - != 32) + for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX) + if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX) goto exit; } else { if (i2c_smbus_write_byte(client, slice << 5)) { diff --git a/trunk/drivers/i2c/chips/max6875.c b/trunk/drivers/i2c/chips/max6875.c index e9e9e5171b53..76645c142977 100644 --- a/trunk/drivers/i2c/chips/max6875.c +++ b/trunk/drivers/i2c/chips/max6875.c @@ -106,7 +106,6 @@ static void max6875_update_slice(struct i2c_client *client, int slice) I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLK_READ, - SLICE_SIZE, buf) != SLICE_SIZE) { goto exit_up; } diff --git a/trunk/drivers/i2c/chips/tsl2550.c b/trunk/drivers/i2c/chips/tsl2550.c deleted file mode 100644 index 3de4b19ba08f..000000000000 --- a/trunk/drivers/i2c/chips/tsl2550.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * tsl2550.c - Linux kernel modules for ambient light sensor - * - * Copyright (C) 2007 Rodolfo Giometti - * Copyright (C) 2007 Eurotech S.p.A. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include - -#define TSL2550_DRV_NAME "tsl2550" -#define DRIVER_VERSION "1.1.1" - -/* - * Defines - */ - -#define TSL2550_POWER_DOWN 0x00 -#define TSL2550_POWER_UP 0x03 -#define TSL2550_STANDARD_RANGE 0x18 -#define TSL2550_EXTENDED_RANGE 0x1d -#define TSL2550_READ_ADC0 0x43 -#define TSL2550_READ_ADC1 0x83 - -/* - * Structs - */ - -struct tsl2550_data { - struct i2c_client *client; - struct mutex update_lock; - - unsigned int power_state : 1; - unsigned int operating_mode : 1; -}; - -/* - * Global data - */ - -static const u8 TSL2550_MODE_RANGE[2] = { - TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE, -}; - -/* - * Management functions - */ - -static int tsl2550_set_operating_mode(struct i2c_client *client, int mode) -{ - struct tsl2550_data *data = i2c_get_clientdata(client); - - int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]); - - data->operating_mode = mode; - - return ret; -} - -static int tsl2550_set_power_state(struct i2c_client *client, int state) -{ - struct tsl2550_data *data = i2c_get_clientdata(client); - int ret; - - if (state == 0) - ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN); - else { - ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP); - - /* On power up we should reset operating mode also... */ - tsl2550_set_operating_mode(client, data->operating_mode); - } - - data->power_state = state; - - return ret; -} - -static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd) -{ - unsigned long end; - int loop = 0, ret = 0; - - /* - * Read ADC channel waiting at most 400ms (see data sheet for further - * info). - * To avoid long busy wait we spin for few milliseconds then - * start sleeping. - */ - end = jiffies + msecs_to_jiffies(400); - while (time_before(jiffies, end)) { - i2c_smbus_write_byte(client, cmd); - - if (loop++ < 5) - mdelay(1); - else - msleep(1); - - ret = i2c_smbus_read_byte(client); - if (ret < 0) - return ret; - else if (ret & 0x0080) - break; - } - if (!(ret & 0x80)) - return -EIO; - return ret & 0x7f; /* remove the "valid" bit */ -} - -/* - * LUX calculation - */ - -#define TSL2550_MAX_LUX 1846 - -static const u8 ratio_lut[] = { - 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 100, 100, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 98, 98, 98, 98, 98, - 98, 98, 97, 97, 97, 97, 97, 96, - 96, 96, 96, 95, 95, 95, 94, 94, - 93, 93, 93, 92, 92, 91, 91, 90, - 89, 89, 88, 87, 87, 86, 85, 84, - 83, 82, 81, 80, 79, 78, 77, 75, - 74, 73, 71, 69, 68, 66, 64, 62, - 60, 58, 56, 54, 52, 49, 47, 44, - 42, 41, 40, 40, 39, 39, 38, 38, - 37, 37, 37, 36, 36, 36, 35, 35, - 35, 35, 34, 34, 34, 34, 33, 33, - 33, 33, 32, 32, 32, 32, 32, 31, - 31, 31, 31, 31, 30, 30, 30, 30, - 30, -}; - -static const u16 count_lut[] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, - 49, 53, 57, 61, 65, 69, 73, 77, - 81, 85, 89, 93, 97, 101, 105, 109, - 115, 123, 131, 139, 147, 155, 163, 171, - 179, 187, 195, 203, 211, 219, 227, 235, - 247, 263, 279, 295, 311, 327, 343, 359, - 375, 391, 407, 423, 439, 455, 471, 487, - 511, 543, 575, 607, 639, 671, 703, 735, - 767, 799, 831, 863, 895, 927, 959, 991, - 1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487, - 1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999, - 2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991, - 3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015, -}; - -/* - * This function is described into Taos TSL2550 Designer's Notebook - * pages 2, 3. - */ -static int tsl2550_calculate_lux(u8 ch0, u8 ch1) -{ - unsigned int lux; - - /* Look up count from channel values */ - u16 c0 = count_lut[ch0]; - u16 c1 = count_lut[ch1]; - - /* - * Calculate ratio. - * Note: the "128" is a scaling factor - */ - u8 r = 128; - - /* Avoid division by 0 and count 1 cannot be greater than count 0 */ - if (c0 && (c1 <= c0)) - r = c1 * 128 / c0; - else - return -1; - - /* Calculate LUX */ - lux = ((c0 - c1) * ratio_lut[r]) / 256; - - /* LUX range check */ - return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux; -} - -/* - * SysFS support - */ - -static ssize_t tsl2550_show_power_state(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev)); - - return sprintf(buf, "%u\n", data->power_state); -} - -static ssize_t tsl2550_store_power_state(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tsl2550_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - int ret; - - if (val < 0 || val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - ret = tsl2550_set_power_state(client, val); - mutex_unlock(&data->update_lock); - - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, - tsl2550_show_power_state, tsl2550_store_power_state); - -static ssize_t tsl2550_show_operating_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev)); - - return sprintf(buf, "%u\n", data->operating_mode); -} - -static ssize_t tsl2550_store_operating_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tsl2550_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - int ret; - - if (val < 0 || val > 1) - return -EINVAL; - - if (data->power_state == 0) - return -EBUSY; - - mutex_lock(&data->update_lock); - ret = tsl2550_set_operating_mode(client, val); - mutex_unlock(&data->update_lock); - - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO, - tsl2550_show_operating_mode, tsl2550_store_operating_mode); - -static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf) -{ - u8 ch0, ch1; - int ret; - - ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0); - if (ret < 0) - return ret; - ch0 = ret; - - mdelay(1); - - ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1); - if (ret < 0) - return ret; - ch1 = ret; - - /* Do the job */ - ret = tsl2550_calculate_lux(ch0, ch1); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", ret); -} - -static ssize_t tsl2550_show_lux1_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tsl2550_data *data = i2c_get_clientdata(client); - int ret; - - /* No LUX data if not operational */ - if (!data->power_state) - return -EBUSY; - - mutex_lock(&data->update_lock); - ret = __tsl2550_show_lux(client, buf); - mutex_unlock(&data->update_lock); - - return ret; -} - -static DEVICE_ATTR(lux1_input, S_IRUGO, - tsl2550_show_lux1_input, NULL); - -static struct attribute *tsl2550_attributes[] = { - &dev_attr_power_state.attr, - &dev_attr_operating_mode.attr, - &dev_attr_lux1_input.attr, - NULL -}; - -static const struct attribute_group tsl2550_attr_group = { - .attrs = tsl2550_attributes, -}; - -/* - * Initialization function - */ - -static int tsl2550_init_client(struct i2c_client *client) -{ - struct tsl2550_data *data = i2c_get_clientdata(client); - int err; - - /* - * Probe the chip. To do so we try to power up the device and then to - * read back the 0x03 code - */ - err = i2c_smbus_write_byte(client, TSL2550_POWER_UP); - if (err < 0) - return err; - mdelay(1); - if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP) - return -ENODEV; - data->power_state = 1; - - /* Set the default operating mode */ - err = i2c_smbus_write_byte(client, - TSL2550_MODE_RANGE[data->operating_mode]); - if (err < 0) - return err; - - return 0; -} - -/* - * I2C init/probing/exit functions - */ - -static struct i2c_driver tsl2550_driver; -static int __devinit tsl2550_probe(struct i2c_client *client) -{ - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct tsl2550_data *data; - int *opmode, err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { - err = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - data->client = client; - i2c_set_clientdata(client, data); - - /* Check platform data */ - opmode = client->dev.platform_data; - if (opmode) { - if (*opmode < 0 || *opmode > 1) { - dev_err(&client->dev, "invalid operating_mode (%d)\n", - *opmode); - err = -EINVAL; - goto exit_kfree; - } - data->operating_mode = *opmode; - } else - data->operating_mode = 0; /* default mode is standard */ - dev_info(&client->dev, "%s operating mode\n", - data->operating_mode ? "extended" : "standard"); - - mutex_init(&data->update_lock); - - /* Initialize the TSL2550 chip */ - err = tsl2550_init_client(client); - if (err) - goto exit_kfree; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group); - if (err) - goto exit_kfree; - - dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION); - - return 0; - -exit_kfree: - kfree(data); -exit: - return err; -} - -static int __devexit tsl2550_remove(struct i2c_client *client) -{ - sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group); - - /* Power down the device */ - tsl2550_set_power_state(client, 0); - - kfree(i2c_get_clientdata(client)); - - return 0; -} - -static struct i2c_driver tsl2550_driver = { - .driver = { - .name = TSL2550_DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = tsl2550_probe, - .remove = __devexit_p(tsl2550_remove), -}; - -static int __init tsl2550_init(void) -{ - return i2c_add_driver(&tsl2550_driver); -} - -static void __exit tsl2550_exit(void) -{ - i2c_del_driver(&tsl2550_driver); -} - -MODULE_AUTHOR("Rodolfo Giometti "); -MODULE_DESCRIPTION("TSL2550 ambient light sensor driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); - -module_init(tsl2550_init); -module_exit(tsl2550_exit); diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index 6971a62397db..435925eba437 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -207,7 +207,6 @@ EXPORT_SYMBOL_GPL(i2c_bus_type); * i2c_new_device - instantiate an i2c device for use with a new style driver * @adap: the adapter managing the device * @info: describes one I2C device; bus_num is ignored - * Context: can sleep * * Create a device to work with a new style i2c driver, where binding is * handled through driver model probe()/remove() methods. This call is not @@ -256,7 +255,6 @@ EXPORT_SYMBOL_GPL(i2c_new_device); /** * i2c_unregister_device - reverse effect of i2c_new_device() * @client: value returned from i2c_new_device() - * Context: can sleep */ void i2c_unregister_device(struct i2c_client *client) { @@ -381,7 +379,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) /** * i2c_add_adapter - declare i2c adapter, use dynamic bus number * @adapter: the adapter to add - * Context: can sleep * * This routine is used to declare an I2C adapter when its bus number * doesn't matter. Examples: for I2C adapters dynamically added by @@ -419,7 +416,6 @@ EXPORT_SYMBOL(i2c_add_adapter); /** * i2c_add_numbered_adapter - declare i2c adapter, use static bus number * @adap: the adapter to register (with adap->nr initialized) - * Context: can sleep * * This routine is used to declare an I2C adapter when its bus number * matters. Example: for I2C adapters from system-on-chip CPUs, or @@ -467,14 +463,6 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) } EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); -/** - * i2c_del_adapter - unregister I2C adapter - * @adap: the adapter being unregistered - * Context: can sleep - * - * This unregisters an I2C adapter which was previously registered - * by @i2c_add_adapter or @i2c_add_numbered_adapter. - */ int i2c_del_adapter(struct i2c_adapter *adap) { struct list_head *item, *_n; @@ -610,7 +598,6 @@ EXPORT_SYMBOL(i2c_register_driver); /** * i2c_del_driver - unregister I2C driver * @driver: the driver being unregistered - * Context: can sleep */ void i2c_del_driver(struct i2c_driver *driver) { @@ -1344,14 +1331,10 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, EXPORT_SYMBOL(i2c_smbus_write_block_data); /* Returns the number of read bytes */ -s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, - u8 length, u8 *values) +s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; - if (length > I2C_SMBUS_BLOCK_MAX) - length = I2C_SMBUS_BLOCK_MAX; - data.block[0] = length; if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, I2C_SMBUS_READ,command, I2C_SMBUS_I2C_BLOCK_DATA,&data)) @@ -1472,7 +1455,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, break; case I2C_SMBUS_I2C_BLOCK_DATA: if (read_write == I2C_SMBUS_READ) { - msg[1].len = data->block[0]; + msg[1].len = I2C_SMBUS_BLOCK_MAX; } else { msg[0].len = data->block[0] + 1; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { @@ -1528,7 +1511,9 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, data->word = msgbuf1[0] | (msgbuf1[1] << 8); break; case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < data->block[0]; i++) + /* fixed at 32 for now */ + data->block[0] = I2C_SMBUS_BLOCK_MAX; + for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) data->block[i+1] = msgbuf1[i]; break; case I2C_SMBUS_BLOCK_DATA: diff --git a/trunk/drivers/i2c/i2c-dev.c b/trunk/drivers/i2c/i2c-dev.c index 64eee9551b22..e7a709710592 100644 --- a/trunk/drivers/i2c/i2c-dev.c +++ b/trunk/drivers/i2c/i2c-dev.c @@ -283,7 +283,6 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, (data_arg.size != I2C_SMBUS_WORD_DATA) && (data_arg.size != I2C_SMBUS_PROC_CALL) && (data_arg.size != I2C_SMBUS_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { dev_dbg(&client->adapter->dev, @@ -330,18 +329,10 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, if ((data_arg.size == I2C_SMBUS_PROC_CALL) || (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || (data_arg.read_write == I2C_SMBUS_WRITE)) { if (copy_from_user(&temp, data_arg.data, datasize)) return -EFAULT; } - if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { - /* Convert old I2C block commands to the new - convention. This preserves binary compatibility. */ - data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; - if (data_arg.read_write == I2C_SMBUS_READ) - temp.block[0] = I2C_SMBUS_BLOCK_MAX; - } res = i2c_smbus_xfer(client->adapter,client->addr,client->flags, data_arg.read_write, data_arg.command,data_arg.size,&temp); diff --git a/trunk/drivers/ide/legacy/hd.c b/trunk/drivers/ide/legacy/hd.c index 8f2db8dd35f7..7f4c0a5050a1 100644 --- a/trunk/drivers/ide/legacy/hd.c +++ b/trunk/drivers/ide/legacy/hd.c @@ -719,25 +719,74 @@ static int __init hd_init(void) device_timer.function = hd_times_out; blk_queue_hardsect_size(hd_queue, 512); +#ifdef __i386__ if (!NR_HD) { - /* - * We don't know anything about the drive. This means + extern struct drive_info drive_info; + unsigned char *BIOS = (unsigned char *) &drive_info; + unsigned long flags; + int cmos_disks; + + for (drive=0 ; drive<2 ; drive++) { + hd_info[drive].cyl = *(unsigned short *) BIOS; + hd_info[drive].head = *(2+BIOS); + hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); + hd_info[drive].ctl = *(8+BIOS); + hd_info[drive].lzone = *(unsigned short *) (12+BIOS); + hd_info[drive].sect = *(14+BIOS); +#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp + if (hd_info[drive].cyl && NR_HD == drive) + NR_HD++; +#endif + BIOS += 16; + } + + /* + We query CMOS about hard disks : it could be that + we have a SCSI/ESDI/etc controller that is BIOS + compatible with ST-506, and thus showing up in our + BIOS table, but not register compatible, and therefore + not present in CMOS. + + Furthermore, we will assume that our ST-506 drives + are the primary drives in the system, and + the ones reflected as drive 1 or 2. + + The first drive is stored in the high nibble of CMOS + byte 0x12, the second in the low nibble. This will be + either a 4 bit drive type or 0xf indicating use byte 0x19 + for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. + + Needless to say, a non-zero value means we have + an AT controller hard disk for that drive. + + Currently the rtc_lock is a bit academic since this + driver is non-modular, but someday... ? Paul G. + */ + + spin_lock_irqsave(&rtc_lock, flags); + cmos_disks = CMOS_READ(0x12); + spin_unlock_irqrestore(&rtc_lock, flags); + + if (cmos_disks & 0xf0) { + if (cmos_disks & 0x0f) + NR_HD = 2; + else + NR_HD = 1; + } + } +#endif /* __i386__ */ +#ifdef __arm__ + if (!NR_HD) { + /* We don't know anything about the drive. This means * that you *MUST* specify the drive parameters to the * kernel yourself. - * - * If we were on an i386, we used to read this info from - * the BIOS or CMOS. This doesn't work all that well, - * since this assumes that this is a primary or secondary - * drive, and if we're using this legacy driver, it's - * probably an auxilliary controller added to recover - * legacy data off an ST-506 drive. Either way, it's - * definitely safest to have the user explicitly specify - * the information. */ printk("hd: no drives specified - use hd=cyl,head,sectors" " on kernel command line\n"); - goto out; } +#endif + if (!NR_HD) + goto out; for (drive=0 ; drive < NR_HD ; drive++) { struct gendisk *disk = alloc_disk(64); diff --git a/trunk/drivers/macintosh/windfarm_smu_sat.c b/trunk/drivers/macintosh/windfarm_smu_sat.c index 351982bcec1b..1043b39aa123 100644 --- a/trunk/drivers/macintosh/windfarm_smu_sat.c +++ b/trunk/drivers/macintosh/windfarm_smu_sat.c @@ -67,6 +67,26 @@ static struct i2c_driver wf_sat_driver = { .detach_client = wf_sat_detach, }; +/* + * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested + * length down to the low-level driver, so we use this, which + * works well enough with the SMU i2c driver code... + */ +static int sat_read_block(struct i2c_client *client, u8 command, + u8 *values, int len) +{ + union i2c_smbus_data data; + int err; + + data.block[0] = len; + err = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA, + &data); + if (!err) + memcpy(values, data.block, len); + return err; +} + struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, unsigned int *size) { @@ -104,8 +124,8 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, return NULL; for (i = 0; i < len; i += 4) { - err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); - if (err < 0) { + err = sat_read_block(&sat->i2c, 0xa, data, 4); + if (err) { printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", err); goto fail; @@ -137,8 +157,8 @@ static int wf_sat_read_cache(struct wf_sat *sat) { int err; - err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); - if (err < 0) + err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16); + if (err) return err; sat->last_read = jiffies; #ifdef LOTSA_DEBUG diff --git a/trunk/drivers/rtc/rtc-x1205.c b/trunk/drivers/rtc/rtc-x1205.c index b3fae357ca49..513d1a611aab 100644 --- a/trunk/drivers/rtc/rtc-x1205.c +++ b/trunk/drivers/rtc/rtc-x1205.c @@ -9,9 +9,6 @@ * * based on a lot of other RTC drivers. * - * Information and datasheet: - * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -29,7 +26,7 @@ * Two bytes need to be written to read a single register, * while most other chips just require one and take the second * one as the data to be written. To prevent corrupting - * unknown chips, the user must explicitly set the probe parameter. + * unknown chips, the user must explicitely set the probe parameter. */ static unsigned short normal_i2c[] = { I2C_CLIENT_END }; diff --git a/trunk/drivers/video/matrox/matroxfb_crtc2.h b/trunk/drivers/video/matrox/matroxfb_crtc2.h index 177177609be7..608e40bb20e9 100644 --- a/trunk/drivers/video/matrox/matroxfb_crtc2.h +++ b/trunk/drivers/video/matrox/matroxfb_crtc2.h @@ -2,6 +2,8 @@ #define __MATROXFB_CRTC2_H__ #include +#include +#include #include "matroxfb_base.h" struct matroxfb_dh_fb_info { diff --git a/trunk/include/asm-blackfin/mach-bf548/anomaly.h b/trunk/include/asm-blackfin/mach-bf548/anomaly.h new file mode 100644 index 000000000000..ddc150e6fb0f --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/anomaly.h @@ -0,0 +1,72 @@ + +/* + * File: include/asm-blackfin/mach-bf548/anomaly.h + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: + * + * Modified: + * + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MACH_ANOMALY_H_ +#define _MACH_ANOMALY_H_ +#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in + slot1 and store of a P register in slot 2 is not + supported */ +#define ANOMALY_05000119 /* DMA_RUN bit is not valid after a Peripheral Receive + Channel DMA stops */ +#define ANOMALY_05000122 /* Rx.H can not be used to access 16-bit System MMR + registers. */ +#define ANOMALY_05000245 /* Spurious Hardware Error from an Access in the + Shadow of a Conditional Branch */ +#define ANOMALY_05000255 /* Entering Hibernate Mode with RTC Seconds event + interrupt not functional */ +#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on + SPORT external receive and transmit clocks. */ +#define ANOMALY_05000272 /* Certain data cache write through modes fail for + VDDint <=0.9V */ +#define ANOMALY_05000310 /* False Hardware Errors Caused by Fetches at the + Boundary of Reserved Memory */ +#define ANOMALY_05000312 /* Errors When SSYNC, CSYNC, or Loads to LT, LB and + LC Registers Are Interrupted */ +#define ANOMALY_05000324 /* TWI Slave Boot Mode Is Not Functional */ +#define ANOMALY_05000325 /* External FIFO Boot Mode Is Not Functional */ +#define ANOMALY_05000327 /* Data Lost When Core and DMA Accesses Are Made to + the USB FIFO Simultaneously */ +#define ANOMALY_05000328 /* Incorrect Access of OTP_STATUS During otp_write() + function */ +#define ANOMALY_05000329 /* Synchronous Burst Flash Boot Mode Is Not Functional + */ +#define ANOMALY_05000330 /* Host DMA Boot Mode Is Not Functional */ +#define ANOMALY_05000334 /* Inadequate Timing Margins on DDR DQS to DQ and DQM + Skew */ +#define ANOMALY_05000335 /* Inadequate Rotary Debounce Logic Duration */ +#define ANOMALY_05000336 /* Phantom Interrupt Occurs After First Configuration + of Host DMA Port */ +#define ANOMALY_05000337 /* Disallowed Configuration Prevents Subsequent + Allowed Configuration on Host DMA Port */ +#define ANOMALY_05000338 /* Slave-Mode SPI0 MISO Failure With CPHA = 0 */ + +#endif /* _MACH_ANOMALY_H_ */ diff --git a/trunk/include/asm-blackfin/mach-bf548/bf548.h b/trunk/include/asm-blackfin/mach-bf548/bf548.h new file mode 100644 index 000000000000..0b211020443d --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/bf548.h @@ -0,0 +1,284 @@ +/* + * File: include/asm-blackfin/mach-bf548/bf548.h + * Based on: + * Author: + * + * Created: + * Description: System MMR register and memory map for ADSP-BF548 + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MACH_BF548_H__ +#define __MACH_BF548_H__ + +/* Masks for generic ERROR IRQ demultiplexing used in int-priority-sc.c */ + +#define SPI_ERR_MASK (TXCOL | RBSY | MODF | TXE) /* SPI_STAT */ +#define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF) /* SPORTx_STAT */ +#define PPI_ERR_MASK (0xFFFF & ~FLD) /* PPI_STATUS */ +#define UART_ERR_MASK_STAT1 (0x4) /* UARTx_IIR */ +#define UART_ERR_MASK_STAT0 (0x2) /* UARTx_IIR */ +#define CAN_ERR_MASK (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | \ + RMLIF | UCEIF | EXTIF | ADIF) /* CAN_GIF */ + +#define OFFSET_(x) ((x) & 0x0000FFFF) + +/*some misc defines*/ +#define IMASK_IVG15 0x8000 +#define IMASK_IVG14 0x4000 +#define IMASK_IVG13 0x2000 +#define IMASK_IVG12 0x1000 + +#define IMASK_IVG11 0x0800 +#define IMASK_IVG10 0x0400 +#define IMASK_IVG9 0x0200 +#define IMASK_IVG8 0x0100 + +#define IMASK_IVG7 0x0080 +#define IMASK_IVGTMR 0x0040 +#define IMASK_IVGHW 0x0020 + +/***************************/ + + +#define BLKFIN_DSUBBANKS 4 +#define BLKFIN_DWAYS 2 +#define BLKFIN_DLINES 64 +#define BLKFIN_ISUBBANKS 4 +#define BLKFIN_IWAYS 4 +#define BLKFIN_ILINES 32 + +#define WAY0_L 0x1 +#define WAY1_L 0x2 +#define WAY01_L 0x3 +#define WAY2_L 0x4 +#define WAY02_L 0x5 +#define WAY12_L 0x6 +#define WAY012_L 0x7 + +#define WAY3_L 0x8 +#define WAY03_L 0x9 +#define WAY13_L 0xA +#define WAY013_L 0xB + +#define WAY32_L 0xC +#define WAY320_L 0xD +#define WAY321_L 0xE +#define WAYALL_L 0xF + +#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */ + +/********************************* EBIU Settings ************************************/ +#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0) +#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2) + +#ifdef CONFIG_C_AMBEN_ALL +#define V_AMBEN AMBEN_ALL +#endif +#ifdef CONFIG_C_AMBEN +#define V_AMBEN 0x0 +#endif +#ifdef CONFIG_C_AMBEN_B0 +#define V_AMBEN AMBEN_B0 +#endif +#ifdef CONFIG_C_AMBEN_B0_B1 +#define V_AMBEN AMBEN_B0_B1 +#endif +#ifdef CONFIG_C_AMBEN_B0_B1_B2 +#define V_AMBEN AMBEN_B0_B1_B2 +#endif +#ifdef CONFIG_C_AMCKEN +#define V_AMCKEN AMCKEN +#else +#define V_AMCKEN 0x0 +#endif +#ifdef CONFIG_C_CDPRIO +#define V_CDPRIO 0x100 +#else +#define V_CDPRIO 0x0 +#endif + +#define AMGCTLVAL (V_AMBEN | V_AMCKEN | V_CDPRIO) + +#define MAX_VC 650000000 +#define MIN_VC 50000000 + +/********************************PLL Settings **************************************/ +#ifdef CONFIG_BFIN_KERNEL_CLOCK +#if (CONFIG_VCO_MULT < 0) +#error "VCO Multiplier is less than 0. Please select a different value" +#endif + +#if (CONFIG_VCO_MULT == 0) +#error "VCO Multiplier should be greater than 0. Please select a different value" +#endif + +#if (CONFIG_VCO_MULT > 64) +#error "VCO Multiplier is more than 64. Please select a different value" +#endif + +#ifndef CONFIG_CLKIN_HALF +#define CONFIG_VCO_HZ (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) +#else +#define CONFIG_VCO_HZ ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2) +#endif + +#ifndef CONFIG_PLL_BYPASS +#define CONFIG_CCLK_HZ (CONFIG_VCO_HZ/CONFIG_CCLK_DIV) +#define CONFIG_SCLK_HZ (CONFIG_VCO_HZ/CONFIG_SCLK_DIV) +#else +#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ +#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ +#endif + +#if (CONFIG_SCLK_DIV < 1) +#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value" +#endif + +#if (CONFIG_SCLK_DIV > 15) +#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value" +#endif + +#if (CONFIG_CCLK_DIV != 1) +#if (CONFIG_CCLK_DIV != 2) +#if (CONFIG_CCLK_DIV != 4) +#if (CONFIG_CCLK_DIV != 8) +#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value" +#endif +#endif +#endif +#endif + +#if (CONFIG_VCO_HZ > MAX_VC) +#error "VCO selected is more than maximum value. Please change the VCO multipler" +#endif + +#if (CONFIG_SCLK_HZ > 133000000) +#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier" +#endif + +#if (CONFIG_SCLK_HZ < 27000000) +#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier" +#endif + +#if (CONFIG_SCLK_HZ >= CONFIG_CCLK_HZ) +#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ) +#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ) +#error "Please select sclk less than cclk" +#endif +#endif +#endif + +#if (CONFIG_CCLK_DIV == 1) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV1 +#endif +#if (CONFIG_CCLK_DIV == 2) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV2 +#endif +#if (CONFIG_CCLK_DIV == 4) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV4 +#endif +#if (CONFIG_CCLK_DIV == 8) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV8 +#endif +#ifndef CONFIG_CCLK_ACT_DIV +#define CONFIG_CCLK_ACT_DIV CONFIG_CCLK_DIV_not_defined_properly +#endif + +#endif /* CONFIG_BFIN_KERNEL_CLOCK */ + +#ifdef CONFIG_BF542 +#define CPU "BF542" +#define CPUID 0x027c8000 +#endif +#ifdef CONFIG_BF544 +#define CPU "BF544" +#define CPUID 0x027c8000 +#endif +#ifdef CONFIG_BF548 +#define CPU "BF548" +#define CPUID 0x027c6000 +#endif +#ifdef CONFIG_BF549 +#define CPU "BF549" +#endif +#ifndef CPU +#define CPU "UNKNOWN" +#define CPUID 0x0 +#endif + +#if (CONFIG_MEM_SIZE % 4) +#error "SDRAM mem size must be multible of 4MB" +#endif + +#define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO) +#define SDRAM_IKERNEL (SDRAM_IGENERIC | CPLB_LOCK) +#define L1_IMEMORY ( CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) +#define SDRAM_INON_CHBL ( CPLB_USER_RD | CPLB_VALID) + +/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/ + +#define ANOMALY_05000158_WORKAROUND 0x200 +#ifdef CONFIG_BLKFIN_WB /*Write Back Policy */ +#define SDRAM_DGENERIC (CPLB_L1_CHBL | CPLB_DIRTY \ + | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND) +#else /*Write Through */ +#define SDRAM_DGENERIC (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW \ + | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY ) +#endif + + +#define L1_DMEMORY (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY ) +#define SDRAM_DNON_CHBL (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY ) +#define SDRAM_EBIU (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY ) +#define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY ) + +#define SIZE_1K 0x00000400 /* 1K */ +#define SIZE_4K 0x00001000 /* 4K */ +#define SIZE_1M 0x00100000 /* 1M */ +#define SIZE_4M 0x00400000 /* 4M */ + +#define MAX_CPLBS (16 * 2) + +/* +* Number of required data CPLB switchtable entries +* MEMSIZE / 4 (we mostly install 4M page size CPLBs +* approx 16 for smaller 1MB page size CPLBs for allignment purposes +* 1 for L1 Data Memory +* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO +* 1 for ASYNC Memory +*/ + + +#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1) * 2) + +/* +* Number of required instruction CPLB switchtable entries +* MEMSIZE / 4 (we mostly install 4M page size CPLBs +* approx 12 for smaller 1MB page size CPLBs for allignment purposes +* 1 for L1 Instruction Memory +* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO +*/ + +#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1) * 2) + +#endif /* __MACH_BF48_H__ */ diff --git a/trunk/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/trunk/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h new file mode 100644 index 000000000000..8f5d9c4d8d5b --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h @@ -0,0 +1,147 @@ +#include +#include + +#define NR_PORTS 2 + +#define OFFSET_THR 0x00 /* Transmit Holding register */ +#define OFFSET_RBR 0x00 /* Receive Buffer register */ +#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */ +#define OFFSET_IER 0x04 /* Interrupt Enable Register */ +#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */ +#define OFFSET_IIR 0x08 /* Interrupt Identification Register */ +#define OFFSET_LCR 0x0C /* Line Control Register */ +#define OFFSET_MCR 0x10 /* Modem Control Register */ +#define OFFSET_LSR 0x14 /* Line Status Register */ +#define OFFSET_MSR 0x18 /* Modem Status Register */ +#define OFFSET_SCR 0x1C /* SCR Scratch Register */ +#define OFFSET_GCTL 0x24 /* Global Control Register */ + +#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR)) +#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL)) +#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER)) +#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH)) +#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR)) +#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR)) +#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR)) +#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL)) + +#define UART_PUT_CHAR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_THR),v) +#define UART_PUT_DLL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLL),v) +#define UART_PUT_IER(uart,v) bfin_write16(((uart)->port.membase + OFFSET_IER),v) +#define UART_PUT_DLH(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLH),v) +#define UART_PUT_LCR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LCR),v) +#define UART_PUT_GCTL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_GCTL),v) + +#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS) +# define CONFIG_SERIAL_BFIN_CTSRTS + +# ifndef CONFIG_UART0_CTS_PIN +# define CONFIG_UART0_CTS_PIN -1 +# endif + +# ifndef CONFIG_UART0_RTS_PIN +# define CONFIG_UART0_RTS_PIN -1 +# endif + +# ifndef CONFIG_UART1_CTS_PIN +# define CONFIG_UART1_CTS_PIN -1 +# endif + +# ifndef CONFIG_UART1_RTS_PIN +# define CONFIG_UART1_RTS_PIN -1 +# endif +#endif +/* + * The pin configuration is different from schematic + */ +struct bfin_serial_port { + struct uart_port port; + unsigned int old_status; +#ifdef CONFIG_SERIAL_BFIN_DMA + int tx_done; + int tx_count; + struct circ_buf rx_dma_buf; + struct timer_list rx_dma_timer; + int rx_dma_nrows; + unsigned int tx_dma_channel; + unsigned int rx_dma_channel; + struct work_struct tx_dma_workqueue; +#else + struct work_struct cts_workqueue; +#endif +#ifdef CONFIG_SERIAL_BFIN_CTSRTS + int cts_pin; + int rts_pin; +#endif +}; + +struct bfin_serial_port bfin_serial_ports[NR_PORTS]; +struct bfin_serial_res { + unsigned long uart_base_addr; + int uart_irq; +#ifdef CONFIG_SERIAL_BFIN_DMA + unsigned int uart_tx_dma_channel; + unsigned int uart_rx_dma_channel; +#endif +#ifdef CONFIG_SERIAL_BFIN_CTSRTS + int uart_cts_pin; + int uart_rts_pin; +#endif +}; + +struct bfin_serial_res bfin_serial_resource[] = { +#ifdef CONFIG_SERIAL_BFIN_UART0 + { + 0xFFC00400, + IRQ_UART0_RX, +#ifdef CONFIG_SERIAL_BFIN_DMA + CH_UART0_TX, + CH_UART0_RX, +#endif +#ifdef CONFIG_BFIN_UART0_CTSRTS + CONFIG_UART0_CTS_PIN, + CONFIG_UART0_RTS_PIN, +#endif + }, +#endif +#ifdef CONFIG_SERIAL_BFIN_UART1 + { + 0xFFC02000, + IRQ_UART1_RX, +#ifdef CONFIG_SERIAL_BFIN_DMA + CH_UART1_TX, + CH_UART1_RX, +#endif +#ifdef CONFIG_BFIN_UART1_CTSRTS + CONFIG_UART1_CTS_PIN, + CONFIG_UART1_RTS_PIN, +#endif + }, +#endif +}; + +int nr_ports = ARRAY_SIZE(bfin_serial_resource); + +static void bfin_serial_hw_init(struct bfin_serial_port *uart) +{ + unsigned short val; + val = bfin_read16(BFIN_PORT_MUX); + val &= ~(PFDE | PFTE); + bfin_write16(BFIN_PORT_MUX, val); + + val = bfin_read16(PORTF_FER); + val |= 0xF; + bfin_write16(PORTF_FER, val); + +#ifdef CONFIG_SERIAL_BFIN_CTSRTS + if (uart->cts_pin >= 0) { + gpio_request(uart->cts_pin, NULL); + gpio_direction_input(uart->cts_pin); + } + + if (uart->rts_pin >= 0) { + gpio_request(uart->rts_pin, NULL); + gpio_direction_output(uart->rts_pin); + } +#endif +} diff --git a/trunk/include/asm-blackfin/mach-bf548/blackfin.h b/trunk/include/asm-blackfin/mach-bf548/blackfin.h new file mode 100644 index 000000000000..094c41a63194 --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/blackfin.h @@ -0,0 +1,166 @@ +/* + * File: include/asm-blackfin/mach-bf548/blackfin.h + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: + * + * Modified: + * + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MACH_BLACKFIN_H_ +#define _MACH_BLACKFIN_H_ + +#define BF548_FAMILY + +#ifdef CONFIG_BF542 +#include "bf542.h" + +#ifdef CONFIG_BF544 +#include "bf544.h" +#endif + +#ifdef CONFIG_BF548 +#include "bf548.h" +#endif + +#ifdef CONFIG_BF549 +#include "bf549.h" +#endif + +#include "mem_map.h" +#include "anomaly.h" + +#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY)) +#ifdef CONFIG_BF542 +#include "cdefBF542.h" +#endif + +#ifdef CONFIG_BF544 +#include "cdefBF544.h" +#endif +#ifdef CONFIG_BF548 +#include "cdefBF548.h" +#endif +#ifdef CONFIG_BF549 +#include "cdefBF549.h" +#endif + +/* UART 1*/ +#define bfin_read_UART_THR() bfin_read_UART1_THR() +#define bfin_write_UART_THR(val) bfin_write_UART1_THR(val) +#define bfin_read_UART_RBR() bfin_read_UART1_RBR() +#define bfin_write_UART_RBR(val) bfin_write_UART1_RBR(val) +#define bfin_read_UART_DLL() bfin_read_UART1_DLL() +#define bfin_write_UART_DLL(val) bfin_write_UART1_DLL(val) +#define bfin_read_UART_IER() bfin_read_UART1_IER() +#define bfin_write_UART_IER(val) bfin_write_UART1_IER(val) +#define bfin_read_UART_DLH() bfin_read_UART1_DLH() +#define bfin_write_UART_DLH(val) bfin_write_UART1_DLH(val) +#define bfin_read_UART_IIR() bfin_read_UART1_IIR() +#define bfin_write_UART_IIR(val) bfin_write_UART1_IIR(val) +#define bfin_read_UART_LCR() bfin_read_UART1_LCR() +#define bfin_write_UART_LCR(val) bfin_write_UART1_LCR(val) +#define bfin_read_UART_MCR() bfin_read_UART1_MCR() +#define bfin_write_UART_MCR(val) bfin_write_UART1_MCR(val) +#define bfin_read_UART_LSR() bfin_read_UART1_LSR() +#define bfin_write_UART_LSR(val) bfin_write_UART1_LSR(val) +#define bfin_read_UART_SCR() bfin_read_UART1_SCR() +#define bfin_write_UART_SCR(val) bfin_write_UART1_SCR(val) +#define bfin_read_UART_GCTL() bfin_read_UART1_GCTL() +#define bfin_write_UART_GCTL(val) bfin_write_UART1_GCTL(val) + +#endif + +/* MAP used DEFINES from BF533 to BF54x - so we don't need to change + * them in the driver, kernel, etc. */ + +/* UART_IIR Register */ +#define STATUS(x) ((x << 1) & 0x06) +#define STATUS_P1 0x02 +#define STATUS_P0 0x01 + +/* UART 0*/ + +/* DMA Channnel */ +#define bfin_read_CH_UART_RX() bfin_read_CH_UART1_RX() +#define bfin_write_CH_UART_RX(val) bfin_write_CH_UART1_RX(val) +#define bfin_read_CH_UART_TX() bfin_read_CH_UART1_TX() +#define bfin_write_CH_UART_TX(val) bfin_write_CH_UART1_TX(val) +#define CH_UART_RX CH_UART1_RX +#define CH_UART_TX CH_UART1_TX + +/* System Interrupt Controller */ +#define bfin_read_IRQ_UART_RX() bfin_read_IRQ_UART1_RX() +#define bfin_write_IRQ_UART_RX(val) bfin_write_IRQ_UART1_RX(val) +#define bfin_read_IRQ_UART_TX() bfin_read_IRQ_UART1_TX() +#define bfin_write_IRQ_UART_TX(val) bfin_write_IRQ_UART1_TX(val) +#define bfin_read_IRQ_UART_ERROR() bfin_read_IRQ_UART1_ERROR() +#define bfin_write_IRQ_UART_ERROR(val) bfin_write_IRQ_UART1_ERROR(val) +#define IRQ_UART_RX IRQ_UART1_RX +#define IRQ_UART_TX IRQ_UART1_TX +#define IRQ_UART_ERROR IRQ_UART1_ERROR + +/* MMR Registers*/ +#define bfin_read_UART_THR() bfin_read_UART1_THR() +#define bfin_write_UART_THR(val) bfin_write_UART1_THR(val) +#define bfin_read_UART_RBR() bfin_read_UART1_RBR() +#define bfin_write_UART_RBR(val) bfin_write_UART1_RBR(val) +#define bfin_read_UART_DLL() bfin_read_UART1_DLL() +#define bfin_write_UART_DLL(val) bfin_write_UART1_DLL(val) +#define bfin_read_UART_IER() bfin_read_UART1_IER() +#define bfin_write_UART_IER(val) bfin_write_UART1_IER(val) +#define bfin_read_UART_DLH() bfin_read_UART1_DLH() +#define bfin_write_UART_DLH(val) bfin_write_UART1_DLH(val) +#define bfin_read_UART_IIR() bfin_read_UART1_IIR() +#define bfin_write_UART_IIR(val) bfin_write_UART1_IIR(val) +#define bfin_read_UART_LCR() bfin_read_UART1_LCR() +#define bfin_write_UART_LCR(val) bfin_write_UART1_LCR(val) +#define bfin_read_UART_MCR() bfin_read_UART1_MCR() +#define bfin_write_UART_MCR(val) bfin_write_UART1_MCR(val) +#define bfin_read_UART_LSR() bfin_read_UART1_LSR() +#define bfin_write_UART_LSR(val) bfin_write_UART1_LSR(val) +#define bfin_read_UART_SCR() bfin_read_UART1_SCR() +#define bfin_write_UART_SCR(val) bfin_write_UART1_SCR(val) +#define bfin_read_UART_GCTL() bfin_read_UART1_GCTL() +#define bfin_write_UART_GCTL(val) bfin_write_UART1_GCTL(val) +#define UART_THR UART1_THR +#define UART_RBR UART1_RBR +#define UART_DLL UART1_DLL +#define UART_IER UART1_IER +#define UART_DLH UART1_DLH +#define UART_IIR UART1_IIR +#define UART_LCR UART1_LCR +#define UART_MCR UART1_MCR +#define UART_LSR UART1_LSR +#define UART_SCR UART1_SCR +#define UART_GCTL UART1_GCTL + +/* PLL_DIV Masks */ +#define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */ +#define CCLK_DIV2 CSEL_DIV2 /* CCLK = VCO / 2 */ +#define CCLK_DIV4 CSEL_DIV4 /* CCLK = VCO / 4 */ +#define CCLK_DIV8 CSEL_DIV8 /* CCLK = VCO / 8 */ + +#endif diff --git a/trunk/include/asm-blackfin/mach-bf548/dma.h b/trunk/include/asm-blackfin/mach-bf548/dma.h new file mode 100644 index 000000000000..5a334c813c79 --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/dma.h @@ -0,0 +1,63 @@ +/* + * file: include/asm-blackfin/mach-bf548/dma.h + * based on: + * author: + * + * created: + * description: + * system mmr register map + * rev: + * + * modified: + * + * + * bugs: enter bugs at http://blackfin.uclinux.org/ + * + * this program is free software; you can redistribute it and/or modify + * it under the terms of the gnu general public license as published by + * the free software foundation; either version 2, or (at your option) + * any later version. + * + * this program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. see the + * gnu general public license for more details. + * + * you should have received a copy of the gnu general public license + * along with this program; see the file copying. + * if not, write to the free software foundation, + * 59 temple place - suite 330, boston, ma 02111-1307, usa. + */ + +#ifndef _MACH_DMA_H_ +#define _MACH_DMA_H_ + +#define CH_SPORT0_RX 0 +#define CH_SPORT0_TX 1 +#define CH_SPORT1_RX 2 +#define CH_SPORT1_TX 3 +#define CH_SPI0 4 +#define CH_SPI1 5 +#define CH_UART0_RX 6 +#define CH_UART0_TX 7 +#define CH_UART1_RX 8 +#define CH_UART1_TX 9 +#define CH_ATAPI_RX 10 +#define CH_ATAPI_TX 11 + +#define CH_EPPI0 12 +#define CH_EPPI1 13 +#define CH_EPPI2 14 +#define CH_PIXC_IMAGE 15 +#define CH_PIXC_OVERLAY 16 +#define CH_PIXC_OUTPUT 17 +#define CH_SPORT2_RX 18 +#define CH_SPORT2_TX 19 +#define CH_SPORT3_RX 20 +#define CH_SPORT3_TX 21 +#define CH_SDH 22 +#define CH_SPI2 23 + +#define MAX_BLACKFIN_DMA_CHANNEL CH_SPI2 + +#endif diff --git a/trunk/include/asm-blackfin/mach-bf548/irq.h b/trunk/include/asm-blackfin/mach-bf548/irq.h new file mode 100644 index 000000000000..a7f6703ea1dd --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/irq.h @@ -0,0 +1,306 @@ +/* + * file: include/asm-blackfin/mach-bf548/irq.h + * based on: include/asm-blackfin/mach-bf537/irq.h + * author: Roy Huang (roy.huang@analog.com) + * + * created: + * description: + * system mmr register map + * rev: + * + * modified: + * + * + * bugs: enter bugs at http://blackfin.uclinux.org/ + * + * this program is free software; you can redistribute it and/or modify + * it under the terms of the gnu general public license as published by + * the free software foundation; either version 2, or (at your option) + * any later version. + * + * this program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. see the + * gnu general public license for more details. + * + * you should have received a copy of the gnu general public license + * along with this program; see the file copying. + * if not, write to the free software foundation, + * 59 temple place - suite 330, boston, ma 02111-1307, usa. + */ + +#ifndef _BF548_IRQ_H_ +#define _BF548_IRQ_H_ + +/* + * Interrupt source definitions + Event Source Core Event Name +Core Emulation ** +Events (highest priority) EMU 0 + Reset RST 1 + NMI NMI 2 + Exception EVX 3 + Reserved -- 4 + Hardware Error IVHW 5 + Core Timer IVTMR 6 * + +..... + + Software Interrupt 1 IVG14 31 + Software Interrupt 2 -- + (lowest priority) IVG15 32 * + */ + +#define NR_PERI_INTS 32 + +/* The ABSTRACT IRQ definitions */ +/** the first seven of the following are fixed, the rest you change if you need to **/ +#define IRQ_EMU 0 /* Emulation */ +#define IRQ_RST 1 /* reset */ +#define IRQ_NMI 2 /* Non Maskable */ +#define IRQ_EVX 3 /* Exception */ +#define IRQ_UNUSED 4 /* - unused interrupt*/ +#define IRQ_HWERR 5 /* Hardware Error */ +#define IRQ_CORETMR 6 /* Core timer */ + +#define BFIN_IRQ(x) ((x) + 7) + +#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ +#define IRQ_DMAC0_ERR BFIN_IRQ(1) /* DMAC0 Status Interrupt */ +#define IRQ_EPPI0_ERR BFIN_IRQ(2) /* EPPI0 Error Interrupt */ +#define IRQ_SPORT0_ERR BFIN_IRQ(3) /* SPORT0 Error Interrupt */ +#define IRQ_SPORT1_ERR BFIN_IRQ(4) /* SPORT1 Error Interrupt */ +#define IRQ_SPI0_ERR BFIN_IRQ(5) /* SPI0 Status(Error) Interrupt */ +#define IRQ_UART0_ERR BFIN_IRQ(6) /* UART0 Status(Error) Interrupt */ +#define IRQ_RTC BFIN_IRQ(7) /* RTC Interrupt */ +#define IRQ_EPPI0 BFIN_IRQ(8) /* EPPI0 Interrupt (DMA12) */ +#define IRQ_SPORT0_RX BFIN_IRQ(9) /* SPORT0 RX Interrupt (DMA0) */ +#define IRQ_SPORT0_TX BFIN_IRQ(10) /* SPORT0 TX Interrupt (DMA1) */ +#define IRQ_SPORT1_RX BFIN_IRQ(11) /* SPORT1 RX Interrupt (DMA2) */ +#define IRQ_SPORT1_TX BFIN_IRQ(12) /* SPORT1 TX Interrupt (DMA3) */ +#define IRQ_SPI0 BFIN_IRQ(13) /* SPI0 Interrupt (DMA4) */ +#define IRQ_UART0_RX BFIN_IRQ(14) /* UART0 RX Interrupt (DMA6) */ +#define IRQ_UART0_TX BFIN_IRQ(15) /* UART0 TX Interrupt (DMA7) */ +#define IRQ_TIMER8 BFIN_IRQ(16) /* TIMER 8 Interrupt */ +#define IRQ_TIMER9 BFIN_IRQ(17) /* TIMER 9 Interrupt */ +#define IRQ_TIMER10 BFIN_IRQ(18) /* TIMER 10 Interrupt */ +#define IRQ_PINT0 BFIN_IRQ(19) /* PINT0 Interrupt */ +#define IRQ_PINT1 BFIN_IRQ(20) /* PINT1 Interrupt */ +#define IRQ_MDMAS0 BFIN_IRQ(21) /* MDMA Stream 0 Interrupt */ +#define IRQ_MDMAS1 BFIN_IRQ(22) /* MDMA Stream 1 Interrupt */ +#define IRQ_WATCHDOG BFIN_IRQ(23) /* Watchdog Interrupt */ +#define IRQ_DMAC1_ERR BFIN_IRQ(24) /* DMAC1 Status (Error) Interrupt */ +#define IRQ_SPORT2_ERR BFIN_IRQ(25) /* SPORT2 Error Interrupt */ +#define IRQ_SPORT3_ERR BFIN_IRQ(26) /* SPORT3 Error Interrupt */ +#define IRQ_MXVR BFIN_IRQ(27) /* SPORT3 Error Interrupt */ +#define IRQ_SPI1_ERR BFIN_IRQ(28) /* SPI1 Status (Error) Interrupt */ +#define IRQ_SPI2_ERR BFIN_IRQ(29) /* SPI2 Status (Error) Interrupt */ +#define IRQ_UART1_ERR BFIN_IRQ(30) /* UART1 Status (Error) Interrupt */ +#define IRQ_UART2_ERR BFIN_IRQ(31) /* UART2 Status (Error) Interrupt */ +#define IRQ_CAN0_ERR BFIN_IRQ(32) /* CAN0 Status (Error) Interrupt */ +#define IRQ_SPORT2_RX BFIN_IRQ(33) /* SPORT2 RX (DMA18) Interrupt */ +#define IRQ_SPORT2_TX BFIN_IRQ(34) /* SPORT2 TX (DMA19) Interrupt */ +#define IRQ_SPORT3_RX BFIN_IRQ(35) /* SPORT3 RX (DMA20) Interrupt */ +#define IRQ_SPORT3_TX BFIN_IRQ(36) /* SPORT3 TX (DMA21) Interrupt */ +#define IRQ_EPP1 BFIN_IRQ(37) /* EPP1 (DMA13) Interrupt */ +#define IRQ_EPP2 BFIN_IRQ(38) /* EPP2 (DMA14) Interrupt */ +#define IRQ_SPI1 BFIN_IRQ(39) /* SPI1 (DMA5) Interrupt */ +#define IRQ_SPI2 BFIN_IRQ(40) /* SPI2 (DMA23) Interrupt */ +#define IRQ_UART1_RX BFIN_IRQ(41) /* UART1 RX (DMA8) Interrupt */ +#define IRQ_UART1_TX BFIN_IRQ(42) /* UART1 TX (DMA9) Interrupt */ +#define IRQ_ATAPI_RX BFIN_IRQ(43) /* ATAPI RX (DMA10) Interrupt */ +#define IRQ_ATAPI_TX BFIN_IRQ(44) /* ATAPI TX (DMA11) Interrupt */ +#define IRQ_TWI0 BFIN_IRQ(45) /* TWI0 Interrupt */ +#define IRQ_TWI1 BFIN_IRQ(46) /* TWI1 Interrupt */ +#define IRQ_CAN0_RX BFIN_IRQ(47) /* CAN0 Receive Interrupt */ +#define IRQ_CAN0_TX BFIN_IRQ(48) /* CAN0 Transmit Interrupt */ +#define IRQ_MDMAS2 BFIN_IRQ(49) /* MDMA Stream 2 Interrupt */ +#define IRQ_MDMAS3 BFIN_IRQ(50) /* MDMA Stream 3 Interrupt */ +#define IRQ_MXVR_ERR BFIN_IRQ(51) /* MXVR Status (Error) Interrupt */ +#define IRQ_MXVR_MSG BFIN_IRQ(52) /* MXVR Message Interrupt */ +#define IRQ_MXVR_PKT BFIN_IRQ(53) /* MXVR Packet Interrupt */ +#define IRQ_EPP1_ERR BFIN_IRQ(54) /* EPPI1 Error Interrupt */ +#define IRQ_EPP2_ERR BFIN_IRQ(55) /* EPPI2 Error Interrupt */ +#define IRQ_UART3_ERR BFIN_IRQ(56) /* UART3 Status (Error) Interrupt */ +#define IRQ_HOST_ERR BFIN_IRQ(57) /* HOST Status (Error) Interrupt */ +#define IRQ_PIXC_ERR BFIN_IRQ(59) /* PIXC Status (Error) Interrupt */ +#define IRQ_NFC_ERR BFIN_IRQ(60) /* NFC Error Interrupt */ +#define IRQ_ATAPI_ERR BFIN_IRQ(61) /* ATAPI Error Interrupt */ +#define IRQ_CAN1_ERR BFIN_IRQ(62) /* CAN1 Status (Error) Interrupt */ +#define IRQ_HS_DMA_ERR BFIN_IRQ(63) /* Handshake DMA Status Interrupt */ +#define IRQ_PIXC_IN0 BFIN_IRQ(64) /* PIXC IN0 (DMA15) Interrupt */ +#define IRQ_PIXC_IN1 BFIN_IRQ(65) /* PIXC IN1 (DMA16) Interrupt */ +#define IRQ_PIXC_OUT BFIN_IRQ(66) /* PIXC OUT (DMA17) Interrupt */ +#define IRQ_SDH BFIN_IRQ(67) /* SDH/NFC (DMA22) Interrupt */ +#define IRQ_CNT BFIN_IRQ(68) /* CNT Interrupt */ +#define IRQ_KEY BFIN_IRQ(69) /* KEY Interrupt */ +#define IRQ_CAN1_RX BFIN_IRQ(70) /* CAN1 RX Interrupt */ +#define IRQ_CAN1_TX BFIN_IRQ(71) /* CAN1 TX Interrupt */ +#define IRQ_SDH_MASK0 BFIN_IRQ(72) /* SDH Mask 0 Interrupt */ +#define IRQ_SDH_MASK1 BFIN_IRQ(73) /* SDH Mask 1 Interrupt */ +#define IRQ_USB_INT0 BFIN_IRQ(75) /* USB INT0 Interrupt */ +#define IRQ_USB_INT1 BFIN_IRQ(76) /* USB INT1 Interrupt */ +#define IRQ_USB_INT2 BFIN_IRQ(77) /* USB INT2 Interrupt */ +#define IRQ_USB_DMA BFIN_IRQ(78) /* USB DMA Interrupt */ +#define IRQ_OPTSEC BFIN_IRQ(79) /* OTPSEC Interrupt */ +#define IRQ_TMR0 BFIN_IRQ(86) /* Timer 0 Interrupt */ +#define IRQ_TMR1 BFIN_IRQ(87) /* Timer 1 Interrupt */ +#define IRQ_TMR2 BFIN_IRQ(88) /* Timer 2 Interrupt */ +#define IRQ_TMR3 BFIN_IRQ(89) /* Timer 3 Interrupt */ +#define IRQ_TMR4 BFIN_IRQ(90) /* Timer 4 Interrupt */ +#define IRQ_TMR5 BFIN_IRQ(91) /* Timer 5 Interrupt */ +#define IRQ_TMR6 BFIN_IRQ(92) /* Timer 6 Interrupt */ +#define IRQ_TMR7 BFIN_IRQ(93) /* Timer 7 Interrupt */ +#define IRQ_PINT2 BFIN_IRQ(94) /* PINT2 Interrupt */ +#define IRQ_PINT3 BFIN_IRQ(95) /* PINT3 Interrupt */ + +#define SYS_IRQS IRQ_PINT3 + +#define BFIN_PA_IRQ(x) ((x) + SYS_IRQS + 1) +#define IRQ_PA0 BFIN_PA_IRQ(0) +#define IRQ_PA1 BFIN_PA_IRQ(1) +#define IRQ_PA2 BFIN_PA_IRQ(2) +#define IRQ_PA3 BFIN_PA_IRQ(3) +#define IRQ_PA4 BFIN_PA_IRQ(4) +#define IRQ_PA5 BFIN_PA_IRQ(5) +#define IRQ_PA6 BFIN_PA_IRQ(6) +#define IRQ_PA7 BFIN_PA_IRQ(7) +#define IRQ_PA8 BFIN_PA_IRQ(8) +#define IRQ_PA9 BFIN_PA_IRQ(9) +#define IRQ_PA10 BFIN_PA_IRQ(10) +#define IRQ_PA11 BFIN_PA_IRQ(11) +#define IRQ_PA12 BFIN_PA_IRQ(12) +#define IRQ_PA13 BFIN_PA_IRQ(13) +#define IRQ_PA14 BFIN_PA_IRQ(14) +#define IRQ_PA15 BFIN_PA_IRQ(15) + +#define BFIN_PB_IRQ(x) ((x) + IRQ_PA15 + 1) +#define IRQ_PB0 BFIN_PB_IRQ(0) +#define IRQ_PB1 BFIN_PB_IRQ(1) +#define IRQ_PB2 BFIN_PB_IRQ(2) +#define IRQ_PB3 BFIN_PB_IRQ(3) +#define IRQ_PB4 BFIN_PB_IRQ(4) +#define IRQ_PB5 BFIN_PB_IRQ(5) +#define IRQ_PB6 BFIN_PB_IRQ(6) +#define IRQ_PB7 BFIN_PB_IRQ(7) +#define IRQ_PB8 BFIN_PB_IRQ(8) +#define IRQ_PB9 BFIN_PB_IRQ(9) +#define IRQ_PB10 BFIN_PB_IRQ(10) +#define IRQ_PB11 BFIN_PB_IRQ(11) +#define IRQ_PB12 BFIN_PB_IRQ(12) +#define IRQ_PB13 BFIN_PB_IRQ(13) +#define IRQ_PB14 BFIN_PB_IRQ(14) +#define IRQ_PB15 BFIN_PB_IRQ(15) + +#define BFIN_PC_IRQ(x) ((x) + IRQ_PB15 + 1) +#define IRQ_PC0 BFIN_PC_IRQ(0) +#define IRQ_PC1 BFIN_PC_IRQ(1) +#define IRQ_PC2 BFIN_PC_IRQ(2) +#define IRQ_PC3 BFIN_PC_IRQ(3) +#define IRQ_PC4 BFIN_PC_IRQ(4) +#define IRQ_PC5 BFIN_PC_IRQ(5) +#define IRQ_PC6 BFIN_PC_IRQ(6) +#define IRQ_PC7 BFIN_PC_IRQ(7) +#define IRQ_PC8 BFIN_PC_IRQ(8) +#define IRQ_PC9 BFIN_PC_IRQ(9) +#define IRQ_PC10 BFIN_PC_IRQ(10) +#define IRQ_PC11 BFIN_PC_IRQ(11) +#define IRQ_PC12 BFIN_PC_IRQ(12) +#define IRQ_PC13 BFIN_PC_IRQ(13) +#define IRQ_PC14 BFIN_PC_IRQ(14) +#define IRQ_PC15 BFIN_PC_IRQ(15) + +#define BFIN_PD_IRQ(x) ((x) + IRQ_PC15 + 1) +#define IRQ_PD0 BFIN_PD_IRQ(0) +#define IRQ_PD1 BFIN_PD_IRQ(1) +#define IRQ_PD2 BFIN_PD_IRQ(2) +#define IRQ_PD3 BFIN_PD_IRQ(3) +#define IRQ_PD4 BFIN_PD_IRQ(4) +#define IRQ_PD5 BFIN_PD_IRQ(5) +#define IRQ_PD6 BFIN_PD_IRQ(6) +#define IRQ_PD7 BFIN_PD_IRQ(7) +#define IRQ_PD8 BFIN_PD_IRQ(8) +#define IRQ_PD9 BFIN_PD_IRQ(9) +#define IRQ_PD10 BFIN_PD_IRQ(10) +#define IRQ_PD11 BFIN_PD_IRQ(11) +#define IRQ_PD12 BFIN_PD_IRQ(12) +#define IRQ_PD13 BFIN_PD_IRQ(13) +#define IRQ_PD14 BFIN_PD_IRQ(14) +#define IRQ_PD15 BFIN_PD_IRQ(15) + +#define BFIN_PE_IRQ(x) ((x) + IRQ_PD15 + 1) +#define IRQ_PE0 BFIN_PE_IRQ(0) +#define IRQ_PE1 BFIN_PE_IRQ(1) +#define IRQ_PE2 BFIN_PE_IRQ(2) +#define IRQ_PE3 BFIN_PE_IRQ(3) +#define IRQ_PE4 BFIN_PE_IRQ(4) +#define IRQ_PE5 BFIN_PE_IRQ(5) +#define IRQ_PE6 BFIN_PE_IRQ(6) +#define IRQ_PE7 BFIN_PE_IRQ(7) +#define IRQ_PE8 BFIN_PE_IRQ(8) +#define IRQ_PE9 BFIN_PE_IRQ(9) +#define IRQ_PE10 BFIN_PE_IRQ(10) +#define IRQ_PE11 BFIN_PE_IRQ(11) +#define IRQ_PE12 BFIN_PE_IRQ(12) +#define IRQ_PE13 BFIN_PE_IRQ(13) +#define IRQ_PE14 BFIN_PE_IRQ(14) +#define IRQ_PE15 BFIN_PE_IRQ(15) + + +#ifdef CONFIG_IRQCHIP_DEMUX_GPIO +#define NR_IRQS (IRQ_PH15+1) +#else +#define NR_IRQS (IRQ_UART1_ERROR+1) +#endif + +#define IVG7 7 +#define IVG8 8 +#define IVG9 9 +#define IVG10 10 +#define IVG11 11 +#define IVG12 12 +#define IVG13 13 +#define IVG14 14 +#define IVG15 15 + +/* IAR0 BIT FIELDS*/ +#define IRQ_PLL_WAKEUP_POS 0 +#define IRQ_DMA_ERROR_POS 4 +#define IRQ_ERROR_POS 8 +#define IRQ_RTC_POS 12 +#define IRQ_PPI_POS 16 +#define IRQ_SPORT0_RX_POS 20 +#define IRQ_SPORT0_TX_POS 24 +#define IRQ_SPORT1_RX_POS 28 + +/* IAR1 BIT FIELDS*/ +#define IRQ_SPORT1_TX_POS 0 +#define IRQ_TWI_POS 4 +#define IRQ_SPI_POS 8 +#define IRQ_UART0_RX_POS 12 +#define IRQ_UART0_TX_POS 16 +#define IRQ_UART1_RX_POS 20 +#define IRQ_UART1_TX_POS 24 +#define IRQ_CAN_RX_POS 28 + +/* IAR2 BIT FIELDS*/ +#define IRQ_CAN_TX_POS 0 +#define IRQ_MAC_RX_POS 4 +#define IRQ_MAC_TX_POS 8 +#define IRQ_TMR0_POS 12 +#define IRQ_TMR1_POS 16 +#define IRQ_TMR2_POS 20 +#define IRQ_TMR3_POS 24 +#define IRQ_TMR4_POS 28 + +/* IAR3 BIT FIELDS*/ +#define IRQ_TMR5_POS 0 +#define IRQ_TMR6_POS 4 +#define IRQ_TMR7_POS 8 +#define IRQ_PROG_INTA_POS 12 +#define IRQ_PORTG_INTB_POS 16 +#define IRQ_MEM_DMA0_POS 20 +#define IRQ_MEM_DMA1_POS 24 +#define IRQ_WATCH_POS 28 + +#endif /* _BF537_IRQ_H_ */ diff --git a/trunk/include/asm-blackfin/mach-bf548/mem_init.h b/trunk/include/asm-blackfin/mach-bf548/mem_init.h new file mode 100644 index 000000000000..0cb279e973d7 --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/mem_init.h @@ -0,0 +1,189 @@ +/* + * File: include/asm-blackfin/mach-bf548/mem_init.h + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if (CONFIG_MEM_MT46V32M16) + +#if defined CONFIG_CLKIN_HALF +#define CLKIN_HALF 1 +#else +#define CLKIN_HALF 0 +#endif + +#if defined CONFIG_PLL_BYPASS +#define PLL_BYPASS 1 +#else +#define PLL_BYPASS 0 +#endif + +/***************************************Currently Not Being Used *********************************/ +#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 +#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 +#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ)) +#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 +#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 + +#if (flash_EBIU_AMBCTL_TT > 3) +#define flash_EBIU_AMBCTL0_TT B0TT_4 +#endif +#if (flash_EBIU_AMBCTL_TT == 3) +#define flash_EBIU_AMBCTL0_TT B0TT_3 +#endif +#if (flash_EBIU_AMBCTL_TT == 2) +#define flash_EBIU_AMBCTL0_TT B0TT_2 +#endif +#if (flash_EBIU_AMBCTL_TT < 2) +#define flash_EBIU_AMBCTL0_TT B0TT_1 +#endif + +#if (flash_EBIU_AMBCTL_ST > 3) +#define flash_EBIU_AMBCTL0_ST B0ST_4 +#endif +#if (flash_EBIU_AMBCTL_ST == 3) +#define flash_EBIU_AMBCTL0_ST B0ST_3 +#endif +#if (flash_EBIU_AMBCTL_ST == 2) +#define flash_EBIU_AMBCTL0_ST B0ST_2 +#endif +#if (flash_EBIU_AMBCTL_ST < 2) +#define flash_EBIU_AMBCTL0_ST B0ST_1 +#endif + +#if (flash_EBIU_AMBCTL_HT > 2) +#define flash_EBIU_AMBCTL0_HT B0HT_3 +#endif +#if (flash_EBIU_AMBCTL_HT == 2) +#define flash_EBIU_AMBCTL0_HT B0HT_2 +#endif +#if (flash_EBIU_AMBCTL_HT == 1) +#define flash_EBIU_AMBCTL0_HT B0HT_1 +#endif +#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0) +#define flash_EBIU_AMBCTL0_HT B0HT_0 +#endif +#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0) +#define flash_EBIU_AMBCTL0_HT B0HT_1 +#endif + +#if (flash_EBIU_AMBCTL_WAT > 14) +#define flash_EBIU_AMBCTL0_WAT B0WAT_15 +#endif +#if (flash_EBIU_AMBCTL_WAT == 14) +#define flash_EBIU_AMBCTL0_WAT B0WAT_14 +#endif +#if (flash_EBIU_AMBCTL_WAT == 13) +#define flash_EBIU_AMBCTL0_WAT B0WAT_13 +#endif +#if (flash_EBIU_AMBCTL_WAT == 12) +#define flash_EBIU_AMBCTL0_WAT B0WAT_12 +#endif +#if (flash_EBIU_AMBCTL_WAT == 11) +#define flash_EBIU_AMBCTL0_WAT B0WAT_11 +#endif +#if (flash_EBIU_AMBCTL_WAT == 10) +#define flash_EBIU_AMBCTL0_WAT B0WAT_10 +#endif +#if (flash_EBIU_AMBCTL_WAT == 9) +#define flash_EBIU_AMBCTL0_WAT B0WAT_9 +#endif +#if (flash_EBIU_AMBCTL_WAT == 8) +#define flash_EBIU_AMBCTL0_WAT B0WAT_8 +#endif +#if (flash_EBIU_AMBCTL_WAT == 7) +#define flash_EBIU_AMBCTL0_WAT B0WAT_7 +#endif +#if (flash_EBIU_AMBCTL_WAT == 6) +#define flash_EBIU_AMBCTL0_WAT B0WAT_6 +#endif +#if (flash_EBIU_AMBCTL_WAT == 5) +#define flash_EBIU_AMBCTL0_WAT B0WAT_5 +#endif +#if (flash_EBIU_AMBCTL_WAT == 4) +#define flash_EBIU_AMBCTL0_WAT B0WAT_4 +#endif +#if (flash_EBIU_AMBCTL_WAT == 3) +#define flash_EBIU_AMBCTL0_WAT B0WAT_3 +#endif +#if (flash_EBIU_AMBCTL_WAT == 2) +#define flash_EBIU_AMBCTL0_WAT B0WAT_2 +#endif +#if (flash_EBIU_AMBCTL_WAT == 1) +#define flash_EBIU_AMBCTL0_WAT B0WAT_1 +#endif + +#if (flash_EBIU_AMBCTL_RAT > 14) +#define flash_EBIU_AMBCTL0_RAT B0RAT_15 +#endif +#if (flash_EBIU_AMBCTL_RAT == 14) +#define flash_EBIU_AMBCTL0_RAT B0RAT_14 +#endif +#if (flash_EBIU_AMBCTL_RAT == 13) +#define flash_EBIU_AMBCTL0_RAT B0RAT_13 +#endif +#if (flash_EBIU_AMBCTL_RAT == 12) +#define flash_EBIU_AMBCTL0_RAT B0RAT_12 +#endif +#if (flash_EBIU_AMBCTL_RAT == 11) +#define flash_EBIU_AMBCTL0_RAT B0RAT_11 +#endif +#if (flash_EBIU_AMBCTL_RAT == 10) +#define flash_EBIU_AMBCTL0_RAT B0RAT_10 +#endif +#if (flash_EBIU_AMBCTL_RAT == 9) +#define flash_EBIU_AMBCTL0_RAT B0RAT_9 +#endif +#if (flash_EBIU_AMBCTL_RAT == 8) +#define flash_EBIU_AMBCTL0_RAT B0RAT_8 +#endif +#if (flash_EBIU_AMBCTL_RAT == 7) +#define flash_EBIU_AMBCTL0_RAT B0RAT_7 +#endif +#if (flash_EBIU_AMBCTL_RAT == 6) +#define flash_EBIU_AMBCTL0_RAT B0RAT_6 +#endif +#if (flash_EBIU_AMBCTL_RAT == 5) +#define flash_EBIU_AMBCTL0_RAT B0RAT_5 +#endif +#if (flash_EBIU_AMBCTL_RAT == 4) +#define flash_EBIU_AMBCTL0_RAT B0RAT_4 +#endif +#if (flash_EBIU_AMBCTL_RAT == 3) +#define flash_EBIU_AMBCTL0_RAT B0RAT_3 +#endif +#if (flash_EBIU_AMBCTL_RAT == 2) +#define flash_EBIU_AMBCTL0_RAT B0RAT_2 +#endif +#if (flash_EBIU_AMBCTL_RAT == 1) +#define flash_EBIU_AMBCTL0_RAT B0RAT_1 +#endif + +#define flash_EBIU_AMBCTL0 \ + (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \ + flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN) diff --git a/trunk/include/asm-blackfin/mach-bf548/mem_map.h b/trunk/include/asm-blackfin/mach-bf548/mem_map.h new file mode 100644 index 000000000000..72d80e8a6e81 --- /dev/null +++ b/trunk/include/asm-blackfin/mach-bf548/mem_map.h @@ -0,0 +1,97 @@ +/* + * file: include/asm-blackfin/mach-bf548/mem_map.h + * based on: + * author: + * + * created: + * description: + * Memory MAP Common header file for blackfin BF537/6/4 of processors. + * rev: + * + * modified: + * + * bugs: enter bugs at http://blackfin.uclinux.org/ + * + * this program is free software; you can redistribute it and/or modify + * it under the terms of the gnu general public license as published by + * the free software foundation; either version 2, or (at your option) + * any later version. + * + * this program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. see the + * gnu general public license for more details. + * + * you should have received a copy of the gnu general public license + * along with this program; see the file copying. + * if not, write to the free software foundation, + * 59 temple place - suite 330, boston, ma 02111-1307, usa. + */ + +#ifndef _MEM_MAP_548_H_ +#define _MEM_MAP_548_H_ + +#define COREMMR_BASE 0xFFE00000 /* Core MMRs */ +#define SYSMMR_BASE 0xFFC00000 /* System MMRs */ + +/* Async Memory Banks */ +#define ASYNC_BANK3_BASE 0x2C000000 /* Async Bank 3 */ +#define ASYNC_BANK3_SIZE 0x04000000 /* 64M */ +#define ASYNC_BANK2_BASE 0x28000000 /* Async Bank 2 */ +#define ASYNC_BANK2_SIZE 0x04000000 /* 64M */ +#define ASYNC_BANK1_BASE 0x24000000 /* Async Bank 1 */ +#define ASYNC_BANK1_SIZE 0x04000000 /* 64M */ +#define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */ +#define ASYNC_BANK0_SIZE 0x04000000 /* 64M */ + +/* Boot ROM Memory */ + +#define BOOT_ROM_START 0xEF000000 + +/* Level 1 Memory */ + +/* Memory Map for ADSP-BF548 processors */ +#ifdef CONFIG_BLKFIN_ICACHE +#define BLKFIN_ICACHESIZE (16*1024) +#else +#define BLKFIN_ICACHESIZE (0*1024) +#endif + +#define L1_CODE_START 0xFFA00000 +#define L1_DATA_A_START 0xFF800000 +#define L1_DATA_B_START 0xFF900000 + +#define L1_CODE_LENGTH 0xC000 + +#ifdef CONFIG_BLKFIN_DCACHE + +#ifdef CONFIG_BLKFIN_DCACHE_BANKA +#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0) +#define L1_DATA_A_LENGTH (0x8000 - 0x4000) +#define L1_DATA_B_LENGTH 0x8000 +#define BLKFIN_DCACHESIZE (16*1024) +#define BLKFIN_DSUPBANKS 1 +#else +#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0) +#define L1_DATA_A_LENGTH (0x8000 - 0x4000) +#define L1_DATA_B_LENGTH (0x8000 - 0x4000) +#define BLKFIN_DCACHESIZE (32*1024) +#define BLKFIN_DSUPBANKS 2 +#endif + +#else +#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0) +#define L1_DATA_A_LENGTH 0x8000 +#define L1_DATA_B_LENGTH 0x8000 +#define BLKFIN_DCACHESIZE (0*1024) +#define BLKFIN_DSUPBANKS 0 +#endif /*CONFIG_BLKFIN_DCACHE*/ + +/* Scratch Pad Memory */ + +#if defined(CONFIG_BF54x) +#define L1_SCRATCH_START 0xFFB00000 +#define L1_SCRATCH_LENGTH 0x1000 +#endif + +#endif/* _MEM_MAP_548_H_ */ diff --git a/trunk/include/asm-i386/boot.h b/trunk/include/asm-i386/boot.h index ed8affbf96cb..bd024ab4fe53 100644 --- a/trunk/include/asm-i386/boot.h +++ b/trunk/include/asm-i386/boot.h @@ -1,5 +1,5 @@ -#ifndef _ASM_BOOT_H -#define _ASM_BOOT_H +#ifndef _LINUX_BOOT_H +#define _LINUX_BOOT_H /* Don't touch these, unless you really know what you're doing. */ #define DEF_INITSEG 0x9000 @@ -17,4 +17,4 @@ + (CONFIG_PHYSICAL_ALIGN - 1)) \ & ~(CONFIG_PHYSICAL_ALIGN - 1)) -#endif /* _ASM_BOOT_H */ +#endif /* _LINUX_BOOT_H */ diff --git a/trunk/include/asm-i386/bootparam.h b/trunk/include/asm-i386/bootparam.h deleted file mode 100644 index 427d8652bfde..000000000000 --- a/trunk/include/asm-i386/bootparam.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _ASM_BOOTPARAM_H -#define _ASM_BOOTPARAM_H - -#include -#include -#include -#include -#include -#include