Commit 93234a6b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://lia64.bkbits.net/to-linus-2.5/

into home.transmeta.com:/home/torvalds/v2.5/linux
parents b4f305dd 33169a92
mainmenu_name "Kernel configuration of Linux for IA-64 machines"
mainmenu_name "IA-64 Linux Kernel Configuration"
source init/Config.in
mainmenu_option next_comment
comment 'General setup'
comment 'Processor type and features'
define_bool CONFIG_IA64 y
......@@ -14,13 +14,6 @@ define_bool CONFIG_SBUS n
define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
define_bool CONFIG_ACPI y
define_bool CONFIG_ACPI_EFI y
define_bool CONFIG_ACPI_INTERPRETER y
define_bool CONFIG_ACPI_KERNEL_CONFIG y
fi
choice 'IA-64 processor type' \
"Itanium CONFIG_ITANIUM \
McKinley CONFIG_MCKINLEY" Itanium
......@@ -38,6 +31,13 @@ choice 'Kernel page size' \
16KB CONFIG_IA64_PAGE_SIZE_16KB \
64KB CONFIG_IA64_PAGE_SIZE_64KB" 16KB
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
define_bool CONFIG_ACPI y
define_bool CONFIG_ACPI_EFI y
define_bool CONFIG_ACPI_INTERPRETER y
define_bool CONFIG_ACPI_KERNEL_CONFIG y
fi
if [ "$CONFIG_ITANIUM" = "y" ]; then
define_bool CONFIG_IA64_BRL_EMU y
bool ' Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC
......@@ -136,6 +136,17 @@ else
fi
endmenu
else # ! HP_SIM
mainmenu_option next_comment
comment 'Block devices'
tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
fi
endmenu
fi # !HP_SIM
mainmenu_option next_comment
......@@ -228,15 +239,7 @@ fi
fi # !HP_SIM
if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then
mainmenu_option next_comment
comment 'Simulated drivers'
bool 'Simulated Ethernet ' CONFIG_SIMETH
bool 'Simulated serial driver support' CONFIG_SIM_SERIAL
if [ "$CONFIG_SCSI" != "n" ]; then
bool 'Simulated SCSI disk' CONFIG_SCSI_SIM
fi
endmenu
source arch/ia64/hp/Config.in
fi
......@@ -258,15 +261,6 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
bool ' Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
bool ' Built-in Kernel Debugger support' CONFIG_KDB
dep_tristate ' KDB modules' CONFIG_KDB_MODULES $CONFIG_KDB
if [ "$CONFIG_KDB" = "y" ]; then
bool ' KDB off by default' CONFIG_KDB_OFF
comment ' Load all symbols for debugging is required for KDB'
define_bool CONFIG_KALLSYMS y
else
bool ' Load all symbols for debugging' CONFIG_KALLSYMS
fi
fi
endmenu
......@@ -7,6 +7,14 @@
#
CONFIG_EXPERIMENTAL=y
#
# General setup
#
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
#
# Loadable module support
#
......@@ -50,21 +58,17 @@ CONFIG_IA32_SUPPORT=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
CONFIG_EFI_VARS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_BUSMGR is not set
# CONFIG_ACPI_SYS is not set
# CONFIG_ACPI_CPU is not set
# CONFIG_ACPI_BUTTON is not set
# CONFIG_ACPI_AC is not set
# CONFIG_ACPI_EC is not set
# CONFIG_ACPI_CMBATT is not set
# CONFIG_ACPI_THERMAL is not set
CONFIG_ACPI_BUSMGR=y
CONFIG_ACPI_SYS=y
CONFIG_ACPI_CPU=y
CONFIG_ACPI_BUTTON=y
CONFIG_ACPI_AC=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_CMBATT=y
CONFIG_ACPI_THERMAL=y
CONFIG_PCI=y
CONFIG_PCI_NAMES=y
# CONFIG_HOTPLUG is not set
......@@ -80,7 +84,7 @@ CONFIG_PCI_NAMES=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
# CONFIG_NETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_NETFILTER is not set
CONFIG_FILTER=y
CONFIG_UNIX=y
......@@ -90,6 +94,7 @@ CONFIG_INET=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_IPV6 is not set
......@@ -128,6 +133,7 @@ CONFIG_INET=y
#
# CONFIG_PNP is not set
# CONFIG_ISAPNP is not set
# CONFIG_PNPBIOS is not set
#
# Block devices
......@@ -137,12 +143,18 @@ CONFIG_INET=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
#
# IEEE 1394 (FireWire) support (EXPERIMENTAL)
#
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
......@@ -171,7 +183,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_IDE=y
#
# IDE, ATA and ATAPI Block devices
# ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
......@@ -182,6 +194,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
# CONFIG_IDEDISK_STROKE is not set
# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
# CONFIG_BLK_DEV_IDEDISK_IBM is not set
......@@ -198,17 +211,18 @@ CONFIG_BLK_DEV_IDEFLOPPY=y
CONFIG_BLK_DEV_IDESCSI=y
#
# IDE chipset support/bugfixes
# IDE chipset support
#
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_IDEDMA_PCI_AUTO is not set
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
......@@ -228,6 +242,7 @@ CONFIG_BLK_DEV_PIIX=y
# CONFIG_PIIX_TUNING is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC_ADMA is not set
# CONFIG_BLK_DEV_PDC202XX is not set
# CONFIG_PDC202XX_BURST is not set
# CONFIG_PDC202XX_FORCE is not set
......@@ -237,8 +252,8 @@ CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_IDEDMA_IVB is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_DMA_NONPCI is not set
CONFIG_BLK_DEV_IDE_MODES=y
# CONFIG_BLK_DEV_ATARAID is not set
......@@ -263,7 +278,6 @@ CONFIG_SD_EXTRA_DEVS=40
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
CONFIG_SCSI_DEBUG_QUEUES=y
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
......@@ -298,6 +312,7 @@ CONFIG_SCSI_LOGGING=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_NCR53C8XX is not set
# CONFIG_SCSI_SYM53C8XX is not set
# CONFIG_SCSI_PAS16 is not set
......@@ -329,6 +344,7 @@ CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
#
# Ethernet (10 or 100Mbit)
......@@ -338,7 +354,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNBMAC is not set
# CONFIG_SUNQE is not set
# CONFIG_SUNLANCE is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
......@@ -351,11 +366,9 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
# CONFIG_TULIP is not set
# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
CONFIG_EEPRO100=y
# CONFIG_E100 is not set
# CONFIG_LNE390 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
......@@ -367,12 +380,13 @@ CONFIG_EEPRO100=y
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_NEW_RX_RESET is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_WINBOND_840 is not set
# CONFIG_VIA_RHINE_MMIO is not set
# CONFIG_NET_POCKET is not set
#
......@@ -380,11 +394,13 @@ CONFIG_EEPRO100=y
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
......@@ -409,6 +425,11 @@ CONFIG_EEPRO100=y
#
# CONFIG_WAN is not set
#
# "Tulip" family network device support
#
# CONFIG_NET_TULIP is not set
#
# Amateur Radio support
#
......@@ -425,7 +446,7 @@ CONFIG_EEPRO100=y
# CONFIG_CD_NO_IDESCSI is not set
#
# Input core support
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_KEYBDEV=y
......@@ -434,6 +455,36 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
# CONFIG_GAMEPORT_NS558 is not set
# CONFIG_GAMEPORT_L4 is not set
# CONFIG_INPUT_EMU10K1 is not set
# CONFIG_GAMEPORT_PCIGAME is not set
# CONFIG_GAMEPORT_FM801 is not set
# CONFIG_GAMEPORT_CS461x is not set
CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_JOYSTICK_ANALOG is not set
# CONFIG_JOYSTICK_A3D is not set
# CONFIG_JOYSTICK_ADI is not set
# CONFIG_JOYSTICK_COBRA is not set
# CONFIG_JOYSTICK_GF2K is not set
# CONFIG_JOYSTICK_GRIP is not set
# CONFIG_JOYSTICK_INTERACT is not set
# CONFIG_JOYSTICK_SIDEWINDER is not set
# CONFIG_JOYSTICK_TMDC is not set
# CONFIG_JOYSTICK_IFORCE_USB is not set
# CONFIG_JOYSTICK_IFORCE_232 is not set
# CONFIG_JOYSTICK_WARRIOR is not set
# CONFIG_JOYSTICK_MAGELLAN is not set
# CONFIG_JOYSTICK_SPACEORB is not set
# CONFIG_JOYSTICK_SPACEBALL is not set
# CONFIG_JOYSTICK_STINGER is not set
# CONFIG_JOYSTICK_DB9 is not set
# CONFIG_JOYSTICK_GAMECON is not set
# CONFIG_JOYSTICK_TURBOGRAFX is not set
#
# Character devices
......@@ -442,7 +493,7 @@ CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_SERIAL_ACPI is not set
CONFIG_SERIAL_ACPI=y
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
......@@ -451,7 +502,14 @@ CONFIG_UNIX98_PTY_COUNT=256
#
# I2C support
#
# CONFIG_I2C is not set
CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PHILIPSPAR is not set
# CONFIG_I2C_ELV is not set
# CONFIG_I2C_VELLEMAN is not set
# CONFIG_I2C_ALGOPCF is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PROC=y
#
# Mice
......@@ -461,41 +519,6 @@ CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set
#
# Joysticks
#
# CONFIG_INPUT_GAMEPORT is not set
# CONFIG_INPUT_NS558 is not set
# CONFIG_INPUT_LIGHTNING is not set
# CONFIG_INPUT_PCIGAME is not set
# CONFIG_INPUT_CS461X is not set
# CONFIG_INPUT_EMU10K1 is not set
CONFIG_INPUT_SERIO=y
CONFIG_INPUT_SERPORT=y
#
# Joysticks
#
# CONFIG_INPUT_ANALOG is not set
# CONFIG_INPUT_A3D is not set
# CONFIG_INPUT_ADI is not set
# CONFIG_INPUT_COBRA is not set
# CONFIG_INPUT_GF2K is not set
# CONFIG_INPUT_GRIP is not set
# CONFIG_INPUT_INTERACT is not set
# CONFIG_INPUT_TMDC is not set
# CONFIG_INPUT_SIDEWINDER is not set
# CONFIG_INPUT_IFORCE_USB is not set
# CONFIG_INPUT_IFORCE_232 is not set
# CONFIG_INPUT_WARRIOR is not set
# CONFIG_INPUT_MAGELLAN is not set
# CONFIG_INPUT_SPACEORB is not set
# CONFIG_INPUT_SPACEBALL is not set
# CONFIG_INPUT_STINGER is not set
# CONFIG_INPUT_DB9 is not set
# CONFIG_INPUT_GAMECON is not set
# CONFIG_INPUT_TURBOGRAFX is not set
# CONFIG_QIC02_TAPE is not set
#
......@@ -523,15 +546,12 @@ CONFIG_AGP_I460=y
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_ALI is not set
# CONFIG_AGP_SWORKS is not set
CONFIG_DRM=y
# CONFIG_DRM_NEW is not set
CONFIG_DRM_OLD=y
CONFIG_DRM40_TDFX=y
# CONFIG_DRM40_GAMMA is not set
# CONFIG_DRM40_R128 is not set
# CONFIG_DRM40_RADEON is not set
# CONFIG_DRM40_I810 is not set
# CONFIG_DRM40_MGA is not set
CONFIG_DRM_TDFX=y
# CONFIG_DRM_GAMMA is not set
# CONFIG_DRM_R128 is not set
# CONFIG_DRM_RADEON is not set
# CONFIG_DRM_I810 is not set
# CONFIG_DRM_MGA is not set
#
# Multimedia devices
......@@ -547,12 +567,16 @@ CONFIG_VIDEO_PROC_FS=y
#
# Video Adapters
#
# CONFIG_VIDEO_BT848 is not set
# CONFIG_VIDEO_PMS is not set
# CONFIG_VIDEO_CPIA is not set
# CONFIG_VIDEO_SAA5249 is not set
# CONFIG_TUNER_3036 is not set
# CONFIG_VIDEO_STRADIS is not set
# CONFIG_VIDEO_ZORAN is not set
# CONFIG_VIDEO_ZORAN_BUZ is not set
# CONFIG_VIDEO_ZORAN_DC10 is not set
# CONFIG_VIDEO_ZORAN_LML33 is not set
# CONFIG_VIDEO_ZR36120 is not set
# CONFIG_VIDEO_MEYE is not set
......@@ -583,11 +607,15 @@ CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
CONFIG_EXT3_FS=m
CONFIG_JBD=m
CONFIG_JBD_DEBUG=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_UMSDOS_FS is not set
......@@ -597,10 +625,13 @@ CONFIG_VFAT_FS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_TMPFS is not set
# CONFIG_RAMFS is not set
CONFIG_RAMFS=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
......@@ -625,11 +656,13 @@ CONFIG_EXT2_FS=y
# Network File Systems
#
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
# CONFIG_NFSD_TCP is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
......@@ -644,7 +677,6 @@ CONFIG_LOCKD_V4=y
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
# CONFIG_ZISOFS_FS is not set
# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
......@@ -666,6 +698,7 @@ CONFIG_EFI_PARTITION=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
CONFIG_EFI_PARTITION=y
# CONFIG_SMB_NLS is not set
CONFIG_NLS=y
......@@ -724,6 +757,11 @@ CONFIG_VGA_CONSOLE=y
# Sound
#
CONFIG_SOUND=y
#
# Open Sound System
#
CONFIG_SOUND_PRIME=y
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
......@@ -746,6 +784,11 @@ CONFIG_SOUND_CS4281=y
# CONFIG_SOUND_OSS is not set
# CONFIG_SOUND_TVMIXER is not set
#
# Advanced Linux Sound Architecture
#
# CONFIG_SND is not set
#
# USB support
#
......@@ -760,8 +803,10 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_LONG_TIMEOUT is not set
#
# USB Controllers
# USB Host Controller Drivers
#
# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
CONFIG_USB_UHCI=m
# CONFIG_USB_UHCI_ALT is not set
# CONFIG_USB_OHCI is not set
......@@ -770,6 +815,7 @@ CONFIG_USB_UHCI=m
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_BLUETOOTH is not set
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_STORAGE_DEBUG is not set
......@@ -808,8 +854,11 @@ CONFIG_USB_MOUSE=m
# CONFIG_USB_OV511 is not set
# CONFIG_USB_PWC is not set
# CONFIG_USB_SE401 is not set
# CONFIG_USB_STV680 is not set
# CONFIG_USB_VICAM is not set
# CONFIG_USB_DSBR is not set
# CONFIG_USB_DABUSB is not set
# CONFIG_USB_KONICAWC is not set
#
# USB Network adaptors
......@@ -836,6 +885,7 @@ CONFIG_USB_MOUSE=m
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IPAQ is not set
# CONFIG_USB_SERIAL_IR is not set
# CONFIG_USB_SERIAL_EDGEPORT is not set
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
......@@ -849,6 +899,7 @@ CONFIG_USB_MOUSE=m
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
......@@ -858,6 +909,14 @@ CONFIG_USB_MOUSE=m
# USB Miscellaneous drivers
#
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_AUERSWALD is not set
#
# Library routines
#
# CONFIG_CRC32 is not set
# CONFIG_ZLIB_INFLATE is not set
# CONFIG_ZLIB_DEFLATE is not set
#
# Bluetooth support
......@@ -873,7 +932,16 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_IA64_PRINT_HAZARDS=y
# CONFIG_DISABLE_VHPT is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_IA64_EARLY_PRINTK=y
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_IA64_DEBUG_CMPXCHG is not set
# CONFIG_IA64_DEBUG_IRQ is not set
CONFIG_KDB=y
# CONFIG_KDB_MODULES is not set
# CONFIG_KDB_OFF is not set
#
# Load all symbols for debugging is required for KDB
#
CONFIG_KALLSYMS=y
#
# ia64/platform/hp/Makefile
#
# Copyright (C) 2002 Hewlett-Packard Co.
# David Mosberger-Tang <davidm@hpl.hp.com>
# Copyright (C) 1999 Silicon Graphics, Inc.
# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
#
......@@ -12,6 +14,10 @@ O_TARGET := hp.a
obj-y := hpsim_console.o hpsim_irq.o hpsim_setup.o
obj-$(CONFIG_IA64_GENERIC) += hpsim_machvec.o
obj-$(CONFIG_SIMETH) += simeth.o
obj-$(CONFIG_SIM_SERIAL) += simserial.o
obj-$(CONFIG_SCSI_SIM) += simscsi.o
clean::
include $(TOPDIR)/Rules.make
/*
* Simulated Ethernet Driver
*
* Copyright (C) 1999-2001 Hewlett-Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/in.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/inetdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/notifier.h>
#include <asm/bitops.h>
#include <asm/system.h>
#include <asm/irq.h>
#define SIMETH_RECV_MAX 10
/*
* Maximum possible received frame for Ethernet.
* We preallocate an sk_buff of that size to avoid costly
* memcpy for temporary buffer into sk_buff. We do basically
* what's done in other drivers, like eepro with a ring.
* The difference is, of course, that we don't have real DMA !!!
*/
#define SIMETH_FRAME_SIZE ETH_FRAME_LEN
#define SSC_NETDEV_PROBE 100
#define SSC_NETDEV_SEND 101
#define SSC_NETDEV_RECV 102
#define SSC_NETDEV_ATTACH 103
#define SSC_NETDEV_DETACH 104
#define NETWORK_INTR 8
struct simeth_local {
struct net_device_stats stats;
int simfd; /* descriptor in the simulator */
};
static int simeth_probe1(void);
static int simeth_open(struct net_device *dev);
static int simeth_close(struct net_device *dev);
static int simeth_tx(struct sk_buff *skb, struct net_device *dev);
static int simeth_rx(struct net_device *dev);
static struct net_device_stats *simeth_get_stats(struct net_device *dev);
static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static void set_multicast_list(struct net_device *dev);
static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr);
static char *simeth_version="0.3";
/*
* This variable is used to establish a mapping between the Linux/ia64 kernel
* and the host linux kernel.
*
* As of today, we support only one card, even though most of the code
* is ready for many more. The mapping is then:
* linux/ia64 -> linux/x86
* eth0 -> eth1
*
* In the future, we some string operations, we could easily support up
* to 10 cards (0-9).
*
* The default mapping can be changed on the kernel command line by
* specifying simeth=ethX (or whatever string you want).
*/
static char *simeth_device="eth0"; /* default host interface to use */
static volatile unsigned int card_count; /* how many cards "found" so far */
static int simeth_debug; /* set to 1 to get debug information */
/*
* Used to catch IFF_UP & IFF_DOWN events
*/
static struct notifier_block simeth_dev_notifier = {
simeth_device_event,
0
};
/*
* Function used when using a kernel command line option.
*
* Format: simeth=interface_name (like eth0)
*/
static int __init
simeth_setup(char *str)
{
simeth_device = str;
return 1;
}
__setup("simeth=", simeth_setup);
/*
* Function used to probe for simeth devices when not installed
* as a loadable module
*/
int __init
simeth_probe (void)
{
int r;
printk("simeth: v%s\n", simeth_version);
r = simeth_probe1();
if (r == 0) register_netdevice_notifier(&simeth_dev_notifier);
return r;
}
extern long ia64_ssc (long, long, long, long, int);
extern void ia64_ssc_connect_irq (long intr, long irq);
static inline int
netdev_probe(char *name, unsigned char *ether)
{
return ia64_ssc(__pa(name), __pa(ether), 0,0, SSC_NETDEV_PROBE);
}
static inline int
netdev_connect(int irq)
{
/* XXX Fix me
* this does not support multiple cards
* also no return value
*/
ia64_ssc_connect_irq(NETWORK_INTR, irq);
return 0;
}
static inline int
netdev_attach(int fd, int irq, unsigned int ipaddr)
{
/* this puts the host interface in the right mode (start interupting) */
return ia64_ssc(fd, ipaddr, 0,0, SSC_NETDEV_ATTACH);
}
static inline int
netdev_detach(int fd)
{
/*
* inactivate the host interface (don't interrupt anymore) */
return ia64_ssc(fd, 0,0,0, SSC_NETDEV_DETACH);
}
static inline int
netdev_send(int fd, unsigned char *buf, unsigned int len)
{
return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_SEND);
}
static inline int
netdev_read(int fd, unsigned char *buf, unsigned int len)
{
return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_RECV);
}
/*
* Function shared with module code, so cannot be in init section
*
* So far this function "detects" only one card (test_&_set) but could
* be extended easily.
*
* Return:
* - -ENODEV is no device found
* - -ENOMEM is no more memory
* - 0 otherwise
*/
static int
simeth_probe1(void)
{
unsigned char mac_addr[ETH_ALEN];
struct simeth_local *local;
struct net_device *dev;
int fd, i;
/*
* XXX Fix me
* let's support just one card for now
*/
if (test_and_set_bit(0, &card_count))
return -ENODEV;
/*
* check with the simulator for the device
*/
fd = netdev_probe(simeth_device, mac_addr);
if (fd == -1)
return -ENODEV;
dev = init_etherdev(NULL, sizeof(struct simeth_local));
if (!dev)
return -ENOMEM;
memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr));
dev->irq = ia64_alloc_irq();
/*
* attach the interrupt in the simulator, this does enable interrupts
* until a netdev_attach() is called
*/
netdev_connect(dev->irq);
memset(dev->priv, 0, sizeof(struct simeth_local));
local = dev->priv;
local->simfd = fd; /* keep track of underlying file descriptor */
dev->open = simeth_open;
dev->stop = simeth_close;
dev->hard_start_xmit = simeth_tx;
dev->get_stats = simeth_get_stats;
dev->set_multicast_list = set_multicast_list; /* no yet used */
/* Fill in the fields of the device structure with ethernet-generic values. */
ether_setup(dev);
printk("%s: hosteth=%s simfd=%d, HwAddr", dev->name, simeth_device, local->simfd);
for(i = 0; i < ETH_ALEN; i++) {
printk(" %2.2x", dev->dev_addr[i]);
}
printk(", IRQ %d\n", dev->irq);
return 0;
}
/*
* actually binds the device to an interrupt vector
*/
static int
simeth_open(struct net_device *dev)
{
if (request_irq(dev->irq, simeth_interrupt, 0, "simeth", dev)) {
printk ("simeth: unable to get IRQ %d.\n", dev->irq);
return -EAGAIN;
}
netif_start_queue(dev);
return 0;
}
/* copied from lapbether.c */
static __inline__ int dev_is_ethdev(struct net_device *dev)
{
return ( dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5));
}
/*
* Handler for IFF_UP or IFF_DOWN
*
* The reason for that is that we don't want to be interrupted when the
* interface is down. There is no way to unconnect in the simualtor. Instead
* we use this function to shutdown packet processing in the frame filter
* in the simulator. Thus no interrupts are generated
*
*
* That's also the place where we pass the IP address of this device to the
* simulator so that that we can start filtering packets for it
*
* There may be a better way of doing this, but I don't know which yet.
*/
static int
simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
{
struct net_device *dev = (struct net_device *)ptr;
struct simeth_local *local;
struct in_device *in_dev;
struct in_ifaddr **ifap = NULL;
struct in_ifaddr *ifa = NULL;
int r;
if ( ! dev ) {
printk(KERN_WARNING "simeth_device_event dev=0\n");
return NOTIFY_DONE;
}
if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
/*
* Check whether or not it's for an ethernet device
*
* XXX Fixme: This works only as long as we support one
* type of ethernet device.
*/
if ( !dev_is_ethdev(dev) ) return NOTIFY_DONE;
if ((in_dev=dev->ip_ptr) != NULL) {
for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
if (strcmp(dev->name, ifa->ifa_label) == 0) break;
}
if ( ifa == NULL ) {
printk("simeth_open: can't find device %s's ifa\n", dev->name);
return NOTIFY_DONE;
}
printk("simeth_device_event: %s ipaddr=0x%x\n", dev->name, htonl(ifa->ifa_local));
/*
* XXX Fix me
* if the device was up, and we're simply reconfiguring it, not sure
* we get DOWN then UP.
*/
local = dev->priv;
/* now do it for real */
r = event == NETDEV_UP ?
netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)):
netdev_detach(local->simfd);
printk("simeth: netdev_attach/detach: event=%s ->%d\n", event == NETDEV_UP ? "attach":"detach", r);
return NOTIFY_DONE;
}
static int
simeth_close(struct net_device *dev)
{
netif_stop_queue(dev);
free_irq(dev->irq, dev);
return 0;
}
/*
* Only used for debug
*/
static void
frame_print(unsigned char *from, unsigned char *frame, int len)
{
int i;
printk("%s: (%d) %02x", from, len, frame[0] & 0xff);
for(i=1; i < 6; i++ ) {
printk(":%02x", frame[i] &0xff);
}
printk(" %2x", frame[6] &0xff);
for(i=7; i < 12; i++ ) {
printk(":%02x", frame[i] &0xff);
}
printk(" [%02x%02x]\n", frame[12], frame[13]);
for(i=14; i < len; i++ ) {
printk("%02x ", frame[i] &0xff);
if ( (i%10)==0) printk("\n");
}
printk("\n");
}
/*
* Function used to transmit of frame, very last one on the path before
* going to the simulator.
*/
static int
simeth_tx(struct sk_buff *skb, struct net_device *dev)
{
struct simeth_local *local = (struct simeth_local *)dev->priv;
#if 0
/* ensure we have at least ETH_ZLEN bytes (min frame size) */
unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
/* Where do the extra padding bytes comes from inthe skbuff ? */
#else
/* the real driver in the host system is going to take care of that
* or maybe it's the NIC itself.
*/
unsigned int length = skb->len;
#endif
local->stats.tx_bytes += skb->len;
local->stats.tx_packets++;
if (simeth_debug > 5) frame_print("simeth_tx", skb->data, length);
netdev_send(local->simfd, skb->data, length);
/*
* we are synchronous on write, so we don't simulate a
* trasnmit complete interrupt, thus we don't need to arm a tx
*/
dev_kfree_skb(skb);
return 0;
}
static inline struct sk_buff *
make_new_skb(struct net_device *dev)
{
struct sk_buff *nskb;
/*
* The +2 is used to make sure that the IP header is nicely
* aligned (on 4byte boundary I assume 14+2=16)
*/
nskb = dev_alloc_skb(SIMETH_FRAME_SIZE + 2);
if ( nskb == NULL ) {
printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name);
return NULL;
}
nskb->dev = dev;
skb_reserve(nskb, 2); /* Align IP on 16 byte boundaries */
skb_put(nskb,SIMETH_FRAME_SIZE);
return nskb;
}
/*
* called from interrupt handler to process a received frame
*/
static int
simeth_rx(struct net_device *dev)
{
struct simeth_local *local;
struct sk_buff *skb;
int len;
int rcv_count = SIMETH_RECV_MAX;
local = (struct simeth_local *)dev->priv;
/*
* the loop concept has been borrowed from other drivers
* looks to me like it's a throttling thing to avoid pushing to many
* packets at one time into the stack. Making sure we can process them
* upstream and make forward progress overall
*/
do {
if ( (skb=make_new_skb(dev)) == NULL ) {
printk(KERN_NOTICE "%s: memory squeeze. dropping packet.\n", dev->name);
local->stats.rx_dropped++;
return 0;
}
/*
* Read only one frame at a time
*/
len = netdev_read(local->simfd, skb->data, SIMETH_FRAME_SIZE);
if ( len == 0 ) {
if ( simeth_debug > 0 ) printk(KERN_WARNING "%s: count=%d netdev_read=0\n", dev->name, SIMETH_RECV_MAX-rcv_count);
break;
}
#if 0
/*
* XXX Fix me
* Should really do a csum+copy here
*/
memcpy(skb->data, frame, len);
#endif
skb->protocol = eth_type_trans(skb, dev);
if ( simeth_debug > 6 ) frame_print("simeth_rx", skb->data, len);
/*
* push the packet up & trigger software interrupt
*/
netif_rx(skb);
local->stats.rx_packets++;
local->stats.rx_bytes += len;
} while ( --rcv_count );
return len; /* 0 = nothing left to read, otherwise, we can try again */
}
/*
* Interrupt handler (Yes, we can do it too !!!)
*/
static void
simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
if ( dev == NULL ) {
printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq);
return;
}
/*
* very simple loop because we get interrupts only when receving
*/
while (simeth_rx(dev));
}
static struct net_device_stats *
simeth_get_stats(struct net_device *dev)
{
struct simeth_local *local = (struct simeth_local *) dev->priv;
return &local->stats;
}
/* fake multicast ability */
static void
set_multicast_list(struct net_device *dev)
{
printk(KERN_WARNING "%s: set_multicast_list called\n", dev->name);
}
#ifdef CONFIG_NET_FASTROUTE
static int
simeth_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
{
printk(KERN_WARNING "%s: simeth_accept_fastpath called\n", dev->name);
return -1;
}
#endif
__initcall(simeth_probe);
/*
* Simulated SCSI driver.
*
* Copyright (C) 1999, 2001-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
*
* 02/01/15 David Mosberger Updated for v2.5.1
* 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33
*/
#include <linux/config.h>
#include <linux/blk.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <scsi/scsi.h>
#include <asm/irq.h>
#include "../drivers/scsi/scsi.h"
#include "../drivers/scsi/sd.h"
#include "../drivers/scsi/hosts.h"
#include "simscsi.h"
#define DEBUG_SIMSCSI 1
/* Simulator system calls: */
#define SSC_OPEN 50
#define SSC_CLOSE 51
#define SSC_READ 52
#define SSC_WRITE 53
#define SSC_GET_COMPLETION 54
#define SSC_WAIT_COMPLETION 55
#define SSC_WRITE_ACCESS 2
#define SSC_READ_ACCESS 1
#if DEBUG_SIMSCSI
int simscsi_debug;
# define DBG simscsi_debug
#else
# define DBG 0
#endif
static struct Scsi_Host *host;
static void simscsi_interrupt (unsigned long val);
DECLARE_TASKLET(simscsi_tasklet, simscsi_interrupt, 0);
struct disk_req {
unsigned long addr;
unsigned len;
};
struct disk_stat {
int fd;
unsigned count;
};
extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
static int desc[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
static struct queue_entry {
Scsi_Cmnd *sc;
} queue[SIMSCSI_REQ_QUEUE_LEN];
static int rd, wr;
static atomic_t num_reqs = ATOMIC_INIT(0);
/* base name for default disks */
static char *simscsi_root = DEFAULT_SIMSCSI_ROOT;
#define MAX_ROOT_LEN 128
/*
* used to setup a new base for disk images
* to use /foo/bar/disk[a-z] as disk images
* you have to specify simscsi=/foo/bar/disk on the command line
*/
static int __init
simscsi_setup (char *s)
{
/* XXX Fix me we may need to strcpy() ? */
if (strlen(s) > MAX_ROOT_LEN) {
printk("simscsi_setup: prefix too long---using default %s\n", simscsi_root);
}
simscsi_root = s;
return 1;
}
__setup("simscsi=", simscsi_setup);
static void
simscsi_interrupt (unsigned long val)
{
Scsi_Cmnd *sc;
while ((sc = queue[rd].sc) != 0) {
atomic_dec(&num_reqs);
queue[rd].sc = 0;
if (DBG)
printk("simscsi_interrupt: done with %ld\n", sc->serial_number);
(*sc->scsi_done)(sc);
rd = (rd + 1) % SIMSCSI_REQ_QUEUE_LEN;
}
}
int
simscsi_detect (Scsi_Host_Template *templ)
{
templ->proc_name = "simscsi";
host = scsi_register(templ, 0);
return 1; /* fake one SCSI host adapter */
}
int
simscsi_release (struct Scsi_Host *host)
{
return 0; /* this is easy... */
}
const char *
simscsi_info (struct Scsi_Host *host)
{
return "simulated SCSI host adapter";
}
int
simscsi_abort (Scsi_Cmnd *cmd)
{
printk ("simscsi_abort: unimplemented\n");
return SCSI_ABORT_SUCCESS;
}
int
simscsi_reset (Scsi_Cmnd *cmd, unsigned int reset_flags)
{
printk ("simscsi_reset: unimplemented\n");
return SCSI_RESET_SUCCESS;
}
int
simscsi_biosparam (Disk *disk, kdev_t n, int ip[])
{
int size = disk->capacity;
ip[0] = 64;
ip[1] = 32;
ip[2] = size >> 11;
return 0;
}
static void
simscsi_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset, unsigned long len)
{
struct disk_stat stat;
struct disk_req req;
req.addr = __pa(sc->request_buffer);
req.len = len; /* # of bytes to transfer */
if (sc->request_bufflen < req.len)
return;
stat.fd = desc[sc->target];
if (DBG)
printk("simscsi_%s @ %lx (off %lx)\n",
mode == SSC_READ ? "read":"write", req.addr, offset);
ia64_ssc(stat.fd, 1, __pa(&req), offset, mode);
ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION);
if (stat.count == req.len) {
sc->result = GOOD;
} else {
sc->result = DID_ERROR << 16;
}
}
static void
simscsi_sg_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset)
{
int list_len = sc->use_sg;
struct scatterlist *sl = (struct scatterlist *)sc->buffer;
struct disk_stat stat;
struct disk_req req;
stat.fd = desc[sc->target];
while (list_len) {
req.addr = __pa(page_address(sl->page) + sl->offset);
req.len = sl->length;
if (DBG)
printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n",
mode == SSC_READ ? "read":"write", req.addr, offset,
list_len, sl->length);
ia64_ssc(stat.fd, 1, __pa(&req), offset, mode);
ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION);
/* should not happen in our case */
if (stat.count != req.len) {
sc->result = DID_ERROR << 16;
return;
}
offset += sl->length;
sl++;
list_len--;
}
sc->result = GOOD;
}
/*
* function handling both READ_6/WRITE_6 (non-scatter/gather mode)
* commands.
* Added 02/26/99 S.Eranian
*/
static void
simscsi_readwrite6 (Scsi_Cmnd *sc, int mode)
{
unsigned long offset;
offset = (((sc->cmnd[1] & 0x1f) << 16) | (sc->cmnd[2] << 8) | sc->cmnd[3])*512;
if (sc->use_sg > 0)
simscsi_sg_readwrite(sc, mode, offset);
else
simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512);
}
static void
simscsi_readwrite10 (Scsi_Cmnd *sc, int mode)
{
unsigned long offset;
offset = ( (sc->cmnd[2] << 24) | (sc->cmnd[3] << 16)
| (sc->cmnd[4] << 8) | (sc->cmnd[5] << 0))*512;
if (sc->use_sg > 0)
simscsi_sg_readwrite(sc, mode, offset);
else
simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512);
}
int
simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
{
char fname[MAX_ROOT_LEN+16];
char *buf;
#if DEBUG_SIMSCSI
register long sp asm ("sp");
if (DBG)
printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n",
sc->target, sc->cmnd[0], sc->serial_number, sp, done);
#endif
sc->result = DID_BAD_TARGET << 16;
sc->scsi_done = done;
if (sc->target <= 7 && sc->lun == 0) {
switch (sc->cmnd[0]) {
case INQUIRY:
if (sc->request_bufflen < 35) {
break;
}
sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
desc[sc->target] = ia64_ssc (__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
0, 0, SSC_OPEN);
if (desc[sc->target] < 0) {
/* disk doesn't exist... */
break;
}
buf = sc->request_buffer;
buf[0] = 0; /* magnetic disk */
buf[1] = 0; /* not a removable medium */
buf[2] = 2; /* SCSI-2 compliant device */
buf[3] = 2; /* SCSI-2 response data format */
buf[4] = 31; /* additional length (bytes) */
buf[5] = 0; /* reserved */
buf[6] = 0; /* reserved */
buf[7] = 0; /* various flags */
memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28);
sc->result = GOOD;
break;
case TEST_UNIT_READY:
sc->result = GOOD;
break;
case READ_6:
if (desc[sc->target] < 0 )
break;
simscsi_readwrite6(sc, SSC_READ);
break;
case READ_10:
if (desc[sc->target] < 0 )
break;
simscsi_readwrite10(sc, SSC_READ);
break;
case WRITE_6:
if (desc[sc->target] < 0)
break;
simscsi_readwrite6(sc, SSC_WRITE);
break;
case WRITE_10:
if (desc[sc->target] < 0)
break;
simscsi_readwrite10(sc, SSC_WRITE);
break;
case READ_CAPACITY:
if (desc[sc->target] < 0 || sc->request_bufflen < 8) {
break;
}
buf = sc->request_buffer;
/* pretend to be a 1GB disk (partition table contains real stuff): */
buf[0] = 0x00;
buf[1] = 0x1f;
buf[2] = 0xff;
buf[3] = 0xff;
/* set block size of 512 bytes: */
buf[4] = 0;
buf[5] = 0;
buf[6] = 2;
buf[7] = 0;
sc->result = GOOD;
break;
case MODE_SENSE:
printk("MODE_SENSE\n");
break;
case START_STOP:
printk("START_STOP\n");
break;
default:
panic("simscsi: unknown SCSI command %u\n", sc->cmnd[0]);
}
}
if (sc->result == DID_BAD_TARGET) {
sc->result |= DRIVER_SENSE << 24;
sc->sense_buffer[0] = 0x70;
sc->sense_buffer[2] = 0x00;
}
if (atomic_read(&num_reqs) >= SIMSCSI_REQ_QUEUE_LEN) {
panic("Attempt to queue command while command is pending!!");
}
atomic_inc(&num_reqs);
queue[wr].sc = sc;
wr = (wr + 1) % SIMSCSI_REQ_QUEUE_LEN;
tasklet_schedule(&simscsi_tasklet);
return 0;
}
static Scsi_Host_Template driver_template = SIMSCSI;
#define __initcall(fn) late_initcall(fn)
#include "../drivers/scsi/scsi_module.c"
/*
* Simulated SCSI driver.
*
* Copyright (C) 1999 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#ifndef SIMSCSI_H
#define SIMSCSI_H
#define SIMSCSI_REQ_QUEUE_LEN 64
#define DEFAULT_SIMSCSI_ROOT "/var/ski-disks/sd"
extern int simscsi_detect (Scsi_Host_Template *);
extern int simscsi_release (struct Scsi_Host *);
extern const char *simscsi_info (struct Scsi_Host *);
extern int simscsi_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
extern int simscsi_abort (Scsi_Cmnd *);
extern int simscsi_reset (Scsi_Cmnd *, unsigned int);
extern int simscsi_biosparam (Disk *, kdev_t, int[]);
#define SIMSCSI { \
detect: simscsi_detect, \
release: simscsi_release, \
info: simscsi_info, \
queuecommand: simscsi_queuecommand, \
abort: simscsi_abort, \
reset: simscsi_reset, \
bios_param: simscsi_biosparam, \
can_queue: SIMSCSI_REQ_QUEUE_LEN, \
this_id: -1, \
sg_tablesize: SG_ALL, \
cmd_per_lun: SIMSCSI_REQ_QUEUE_LEN, \
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: DISABLE_CLUSTERING \
}
#endif /* SIMSCSI_H */
/*
* Simulated Serial Driver (fake serial)
*
* This driver is mostly used for bringup purposes and will go away.
* It has a strong dependency on the system console. All outputs
* are rerouted to the same facility as the one used by printk which, in our
* case means sys_sim.c console (goes via the simulator). The code hereafter
* is completely leveraged from the serial.c driver.
*
* Copyright (C) 1999-2000 Hewlett-Packard Co
* Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
*
* 02/04/00 D. Mosberger Merged in serial.c bug fixes in rs_close().
* 02/25/00 D. Mosberger Synced up with 2.3.99pre-5 version of serial.c.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/major.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#ifdef CONFIG_KDB
# include <linux/kdb.h>
#endif
#undef SIMSERIAL_DEBUG /* define this to get some debug information */
#define KEYBOARD_INTR 3 /* must match with simulator! */
#define NR_PORTS 1 /* only one port for now */
#define SERIAL_INLINE 1
#ifdef SERIAL_INLINE
#define _INLINE_ inline
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
#define SSC_GETCHAR 21
extern long ia64_ssc (long, long, long, long, int);
extern void ia64_ssc_connect_irq (long intr, long irq);
static char *serial_name = "SimSerial driver";
static char *serial_version = "0.6";
/*
* This has been extracted from asm/serial.h. We need one eventually but
* I don't know exactly what we're going to put in it so just fake one
* for now.
*/
#define BASE_BAUD ( 1843200 / 16 )
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
/*
* Most of the values here are meaningless to this particular driver.
* However some values must be preserved for the code (leveraged from serial.c
* to work correctly).
* port must not be 0
* type must not be UNKNOWN
* So I picked arbitrary (guess from where?) values instead
*/
static struct serial_state rs_table[NR_PORTS]={
/* UART CLK PORT IRQ FLAGS */
{ 0, BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS,0,PORT_16550 } /* ttyS0 */
};
/*
* Just for the fun of it !
*/
static struct serial_uart_config uart_config[] = {
{ "unknown", 1, 0 },
{ "8250", 1, 0 },
{ "16450", 1, 0 },
{ "16550", 1, 0 },
{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
{ "cirrus", 1, 0 },
{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
UART_STARTECH },
{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
{ 0, 0}
};
static struct tty_driver serial_driver, callout_driver;
static int serial_refcount;
static struct async_struct *IRQ_ports[NR_IRQS];
static struct tty_struct *serial_table[NR_PORTS];
static struct termios *serial_termios[NR_PORTS];
static struct termios *serial_termios_locked[NR_PORTS];
static struct console *console;
static unsigned char *tmp_buf;
static DECLARE_MUTEX(tmp_buf_sem);
extern struct console *console_drivers; /* from kernel/printk.c */
/*
* ------------------------------------------------------------
* rs_stop() and rs_start()
*
* This routines are called before setting or resetting tty->stopped.
* They enable or disable transmitter interrupts, as necessary.
* ------------------------------------------------------------
*/
static void rs_stop(struct tty_struct *tty)
{
#ifdef SIMSERIAL_DEBUG
printk("rs_stop: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
tty->stopped, tty->hw_stopped, tty->flow_stopped);
#endif
}
static void rs_start(struct tty_struct *tty)
{
#if SIMSERIAL_DEBUG
printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
tty->stopped, tty->hw_stopped, tty->flow_stopped);
#endif
}
static void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
{
unsigned char ch;
static unsigned char seen_esc = 0;
while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) {
if ( ch == 27 && seen_esc == 0 ) {
seen_esc = 1;
continue;
} else {
if ( seen_esc==1 && ch == 'O' ) {
seen_esc = 2;
continue;
} else if ( seen_esc == 2 ) {
if ( ch == 'P' ) show_state(); /* F1 key */
if ( ch == 'Q' ) show_buffers(); /* F2 key */
#ifdef CONFIG_KDB
if ( ch == 'S' )
kdb(KDB_REASON_KEYBOARD, 0, (kdb_eframe_t) regs);
#endif
seen_esc = 0;
continue;
}
}
seen_esc = 0;
if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = 0;
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
}
tty_flip_buffer_push(tty);
}
/*
* This is the serial driver's interrupt routine for a single port
*/
static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
{
struct async_struct * info;
/*
* I don't know exactly why they don't use the dev_id opaque data
* pointer instead of this extra lookup table
*/
info = IRQ_ports[irq];
if (!info || !info->tty) {
printk("simrs_interrupt_single: info|tty=0 info=%p problem\n", info);
return;
}
/*
* pretty simple in our case, because we only get interrupts
* on inbound traffic
*/
receive_chars(info->tty, regs);
}
/*
* -------------------------------------------------------------------
* Here ends the serial interrupt routines.
* -------------------------------------------------------------------
*/
#if 0
/*
* not really used in our situation so keep them commented out for now
*/
static DECLARE_TASK_QUEUE(tq_serial); /* used to be at the top of the file */
static void do_serial_bh(void)
{
run_task_queue(&tq_serial);
printk("do_serial_bh: called\n");
}
#endif
static void do_softint(void *private_)
{
printk("simserial: do_softint called\n");
}
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
if (!tty || !info->xmit.buf) return;
save_flags(flags); cli();
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
restore_flags(flags);
return;
}
info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
restore_flags(flags);
}
static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
{
int count;
unsigned long flags;
save_flags(flags); cli();
if (info->x_char) {
char c = info->x_char;
console->write(console, &c, 1);
info->state->icount.tx++;
info->x_char = 0;
goto out;
}
if (info->xmit.head == info->xmit.tail || info->tty->stopped || info->tty->hw_stopped) {
#ifdef SIMSERIAL_DEBUG
printk("transmit_chars: head=%d, tail=%d, stopped=%d\n",
info->xmit.head, info->xmit.tail, info->tty->stopped);
#endif
goto out;
}
/*
* We removed the loop and try to do it in to chunks. We need
* 2 operations maximum because it's a ring buffer.
*
* First from current to tail if possible.
* Then from the beginning of the buffer until necessary
*/
count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
SERIAL_XMIT_SIZE - info->xmit.tail);
console->write(console, info->xmit.buf+info->xmit.tail, count);
info->xmit.tail = (info->xmit.tail+count) & (SERIAL_XMIT_SIZE-1);
/*
* We have more at the beginning of the buffer
*/
count = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (count) {
console->write(console, info->xmit.buf, count);
info->xmit.tail += count;
}
out:
restore_flags(flags);
}
static void rs_flush_chars(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped ||
!info->xmit.buf)
return;
transmit_chars(info, NULL);
}
static int rs_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
int c, ret = 0;
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
if (!tty || !info->xmit.buf || !tmp_buf) return 0;
save_flags(flags);
if (from_user) {
down(&tmp_buf_sem);
while (1) {
int c1;
c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (count < c)
c = count;
if (c <= 0)
break;
c -= copy_from_user(tmp_buf, buf, c);
if (!c) {
if (!ret)
ret = -EFAULT;
break;
}
cli();
c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (c1 < c)
c = c1;
memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
restore_flags(flags);
buf += c;
count -= c;
ret += c;
}
up(&tmp_buf_sem);
} else {
cli();
while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (count < c)
c = count;
if (c <= 0) {
break;
}
memcpy(info->xmit.buf + info->xmit.head, buf, c);
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
buf += c;
count -= c;
ret += c;
}
restore_flags(flags);
}
/*
* Hey, we transmit directly from here in our case
*/
if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE)
&& !tty->stopped && !tty->hw_stopped) {
transmit_chars(info, NULL);
}
return ret;
}
static int rs_write_room(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
}
static int rs_chars_in_buffer(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
}
static void rs_flush_buffer(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
save_flags(flags); cli();
info->xmit.head = info->xmit.tail = 0;
restore_flags(flags);
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
}
/*
* This function is used to send a high-priority XON/XOFF character to
* the device
*/
static void rs_send_xchar(struct tty_struct *tty, char ch)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
info->x_char = ch;
if (ch) {
/*
* I guess we could call console->write() directly but
* let's do that for now.
*/
transmit_chars(info, NULL);
}
}
/*
* ------------------------------------------------------------
* rs_throttle()
*
* This routine is called by the upper-layer tty layer to signal that
* incoming characters should be throttled.
* ------------------------------------------------------------
*/
static void rs_throttle(struct tty_struct * tty)
{
if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty));
printk("simrs_throttle called\n");
}
static void rs_unthrottle(struct tty_struct * tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
else
rs_send_xchar(tty, START_CHAR(tty));
}
printk("simrs_unthrottle called\n");
}
/*
* rs_break() --- routine which turns the break handling on or off
*/
static void rs_break(struct tty_struct *tty, int break_state)
{
}
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
switch (cmd) {
case TIOCMGET:
printk("rs_ioctl: TIOCMGET called\n");
return -EINVAL;
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
printk("rs_ioctl: TIOCMBIS/BIC/SET called\n");
return -EINVAL;
case TIOCGSERIAL:
printk("simrs_ioctl TIOCGSERIAL called\n");
return 0;
case TIOCSSERIAL:
printk("simrs_ioctl TIOCSSERIAL called\n");
return 0;
case TIOCSERCONFIG:
printk("rs_ioctl: TIOCSERCONFIG called\n");
return -EINVAL;
case TIOCSERGETLSR: /* Get line status register */
printk("rs_ioctl: TIOCSERGETLSR called\n");
return -EINVAL;
case TIOCSERGSTRUCT:
printk("rs_ioctl: TIOCSERGSTRUCT called\n");
#if 0
if (copy_to_user((struct async_struct *) arg,
info, sizeof(struct async_struct)))
return -EFAULT;
#endif
return 0;
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
* - mask passed in arg for lines of interest
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
* Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
printk("rs_ioctl: TIOCMIWAIT: called\n");
return 0;
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
* Return: write counters to the user passed counter struct
* NB: both 1->0 and 0->1 transitions are counted except for
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
printk("rs_ioctl: TIOCGICOUNT called\n");
return 0;
case TIOCSERGWILD:
case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
return 0;
default:
return -ENOIOCTLCMD;
}
return 0;
}
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
unsigned int cflag = tty->termios->c_cflag;
if ( (cflag == old_termios->c_cflag)
&& ( RELEVANT_IFLAG(tty->termios->c_iflag)
== RELEVANT_IFLAG(old_termios->c_iflag)))
return;
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
rs_start(tty);
}
}
/*
* This routine will shutdown a serial port; interrupts are disabled, and
* DTR is dropped if the hangup on close termio flag is on.
*/
static void shutdown(struct async_struct * info)
{
unsigned long flags;
struct serial_state *state;
int retval;
if (!(info->flags & ASYNC_INITIALIZED)) return;
state = info->state;
#ifdef SIMSERIAL_DEBUG
printk("Shutting down serial port %d (irq %d)....", info->line,
state->irq);
#endif
save_flags(flags); cli(); /* Disable interrupts */
/*
* First unlink the serial port from the IRQ chain...
*/
if (info->next_port)
info->next_port->prev_port = info->prev_port;
if (info->prev_port)
info->prev_port->next_port = info->next_port;
else
IRQ_ports[state->irq] = info->next_port;
/*
* Free the IRQ, if necessary
*/
if (state->irq && (!IRQ_ports[state->irq] ||
!IRQ_ports[state->irq]->next_port)) {
if (IRQ_ports[state->irq]) {
free_irq(state->irq, NULL);
retval = request_irq(state->irq, rs_interrupt_single,
IRQ_T(info), "serial", NULL);
if (retval)
printk("serial shutdown: request_irq: error %d"
" Couldn't reacquire IRQ.\n", retval);
} else
free_irq(state->irq, NULL);
}
if (info->xmit.buf) {
free_page((unsigned long) info->xmit.buf);
info->xmit.buf = 0;
}
if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
restore_flags(flags);
}
/*
* ------------------------------------------------------------
* rs_close()
*
* This routine is called when the serial port gets closed. First, we
* wait for the last remaining data to be sent. Then, we unlink its
* async structure from the interrupt chain if necessary, and we free
* that IRQ if nothing is left in the chain.
* ------------------------------------------------------------
*/
static void rs_close(struct tty_struct *tty, struct file * filp)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct serial_state *state;
unsigned long flags;
if (!info ) return;
state = info->state;
save_flags(flags); cli();
if (tty_hung_up_p(filp)) {
#ifdef SIMSERIAL_DEBUG
printk("rs_close: hung_up\n");
#endif
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
#ifdef SIMSERIAL_DEBUG
printk("rs_close ttys%d, count = %d\n", info->line, state->count);
#endif
if ((tty->count == 1) && (state->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. state->count should always
* be one in these conditions. If it's greater than
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
printk("rs_close: bad serial port count; tty->count is 1, "
"state->count is %d\n", state->count);
state->count = 1;
}
if (--state->count < 0) {
printk("rs_close: bad serial port count for ttys%d: %d\n",
info->line, state->count);
state->count = 0;
}
if (state->count) {
MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
info->flags |= ASYNC_CLOSING;
restore_flags(flags);
/*
* Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters.
*/
shutdown(info);
if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty);
if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
info->event = 0;
info->tty = 0;
if (info->blocked_open) {
if (info->close_delay) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(info->close_delay);
}
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
MOD_DEC_USE_COUNT;
}
/*
* rs_wait_until_sent() --- wait until the transmitter is empty
*/
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
{
}
/*
* rs_hangup() --- called by tty_hangup() when a hangup is signaled.
*/
static void rs_hangup(struct tty_struct *tty)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct serial_state *state = info->state;
#ifdef SIMSERIAL_DEBUG
printk("rs_hangup: called\n");
#endif
state = info->state;
rs_flush_buffer(tty);
if (info->flags & ASYNC_CLOSING)
return;
shutdown(info);
info->event = 0;
state->count = 0;
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
info->tty = 0;
wake_up_interruptible(&info->open_wait);
}
static int get_async_struct(int line, struct async_struct **ret_info)
{
struct async_struct *info;
struct serial_state *sstate;
sstate = rs_table + line;
sstate->count++;
if (sstate->info) {
*ret_info = sstate->info;
return 0;
}
info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
if (!info) {
sstate->count--;
return -ENOMEM;
}
memset(info, 0, sizeof(struct async_struct));
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->delta_msr_wait);
info->magic = SERIAL_MAGIC;
info->port = sstate->port;
info->flags = sstate->flags;
info->xmit_fifo_size = sstate->xmit_fifo_size;
info->line = line;
info->tqueue.routine = do_softint;
info->tqueue.data = info;
info->state = sstate;
if (sstate->info) {
kfree(info);
*ret_info = sstate->info;
return 0;
}
*ret_info = sstate->info = info;
return 0;
}
static int
startup(struct async_struct *info)
{
unsigned long flags;
int retval=0;
void (*handler)(int, void *, struct pt_regs *);
struct serial_state *state= info->state;
unsigned long page;
page = get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
save_flags(flags); cli();
if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
goto errout;
}
if (!state->port || !state->type) {
if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
free_page(page);
goto errout;
}
if (info->xmit.buf)
free_page(page);
else
info->xmit.buf = (unsigned char *) page;
#ifdef SIMSERIAL_DEBUG
printk("startup: ttys%d (irq %d)...", info->line, state->irq);
#endif
/*
* Allocate the IRQ if necessary
*/
if (state->irq && (!IRQ_ports[state->irq] ||
!IRQ_ports[state->irq]->next_port)) {
if (IRQ_ports[state->irq]) {
retval = -EBUSY;
goto errout;
} else
handler = rs_interrupt_single;
retval = request_irq(state->irq, handler, IRQ_T(info),
"simserial", NULL);
if (retval) {
if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR,
&info->tty->flags);
retval = 0;
}
goto errout;
}
}
/*
* Insert serial port into IRQ chain.
*/
info->prev_port = 0;
info->next_port = IRQ_ports[state->irq];
if (info->next_port)
info->next_port->prev_port = info;
IRQ_ports[state->irq] = info;
if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags);
info->xmit.head = info->xmit.tail = 0;
#if 0
/*
* Set up serial timers...
*/
timer_table[RS_TIMER].expires = jiffies + 2*HZ/100;
timer_active |= 1 << RS_TIMER;
#endif
/*
* Set up the tty->alt_speed kludge
*/
if (info->tty) {
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
info->tty->alt_speed = 57600;
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
info->tty->alt_speed = 115200;
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
info->tty->alt_speed = 230400;
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
info->tty->alt_speed = 460800;
}
info->flags |= ASYNC_INITIALIZED;
restore_flags(flags);
return 0;
errout:
restore_flags(flags);
return retval;
}
/*
* This routine is called whenever a serial port is opened. It
* enables interrupts for a serial port, linking in its async structure into
* the IRQ chain. It also performs the serial-specific
* initialization for the tty structure.
*/
static int rs_open(struct tty_struct *tty, struct file * filp)
{
struct async_struct *info;
int retval, line;
unsigned long page;
MOD_INC_USE_COUNT;
line = minor(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS)) {
MOD_DEC_USE_COUNT;
return -ENODEV;
}
retval = get_async_struct(line, &info);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
tty->driver_data = info;
info->tty = tty;
#ifdef SIMSERIAL_DEBUG
printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
info->state->count);
#endif
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if (!tmp_buf) {
page = get_free_page(GFP_KERNEL);
if (!page) {
/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
return -ENOMEM;
}
if (tmp_buf)
free_page(page);
else
tmp_buf = (unsigned char *) page;
}
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
if (info->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait);
/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
#else
return -EAGAIN;
#endif
}
/*
* Start up serial port
*/
retval = startup(info);
if (retval) {
/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
return retval;
}
if ((info->state->count == 1) &&
(info->flags & ASYNC_SPLIT_TERMIOS)) {
if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
*tty->termios = info->state->normal_termios;
else
*tty->termios = info->state->callout_termios;
}
/*
* figure out which console to use (should be one already)
*/
console = console_drivers;
while (console) {
if ((console->flags & CON_ENABLED) && console->write) break;
console = console->next;
}
info->session = current->session;
info->pgrp = current->pgrp;
#ifdef SIMSERIAL_DEBUG
printk("rs_open ttys%d successful\n", info->line);
#endif
return 0;
}
/*
* /proc fs routines....
*/
static inline int line_info(char *buf, struct serial_state *state)
{
return sprintf(buf, "%d: uart:%s port:%lX irq:%d\n",
state->line, uart_config[state->type].name,
state->port, state->irq);
}
static int rs_read_proc(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int i, len = 0, l;
off_t begin = 0;
len += sprintf(page, "simserinfo:1.0 driver:%s\n", serial_version);
for (i = 0; i < NR_PORTS && len < 4000; i++) {
l = line_info(page + len, &rs_table[i]);
len += l;
if (len+begin > off+count)
goto done;
if (len+begin < off) {
begin += len;
len = 0;
}
}
*eof = 1;
done:
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
}
/*
* ---------------------------------------------------------------------
* rs_init() and friends
*
* rs_init() is called at boot-time to initialize the serial driver.
* ---------------------------------------------------------------------
*/
/*
* This routine prints out the appropriate serial driver version
* number, and identifies which options were configured into this
* driver.
*/
static inline void show_serial_version(void)
{
printk(KERN_INFO "%s version %s with", serial_name, serial_version);
printk(" no serial options enabled\n");
}
/*
* The serial driver boot-time initialization code!
*/
static int __init
simrs_init (void)
{
int i;
struct serial_state *state;
show_serial_version();
/* Initialize the tty_driver structure */
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
serial_driver.driver_name = "simserial";
serial_driver.name = "ttyS";
serial_driver.major = TTY_MAJOR;
serial_driver.minor_start = 64;
serial_driver.num = 1;
serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
serial_driver.subtype = SERIAL_TYPE_NORMAL;
serial_driver.init_termios = tty_std_termios;
serial_driver.init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver.flags = TTY_DRIVER_REAL_RAW;
serial_driver.refcount = &serial_refcount;
serial_driver.table = serial_table;
serial_driver.termios = serial_termios;
serial_driver.termios_locked = serial_termios_locked;
serial_driver.open = rs_open;
serial_driver.close = rs_close;
serial_driver.write = rs_write;
serial_driver.put_char = rs_put_char;
serial_driver.flush_chars = rs_flush_chars;
serial_driver.write_room = rs_write_room;
serial_driver.chars_in_buffer = rs_chars_in_buffer;
serial_driver.flush_buffer = rs_flush_buffer;
serial_driver.ioctl = rs_ioctl;
serial_driver.throttle = rs_throttle;
serial_driver.unthrottle = rs_unthrottle;
serial_driver.send_xchar = rs_send_xchar;
serial_driver.set_termios = rs_set_termios;
serial_driver.stop = rs_stop;
serial_driver.start = rs_start;
serial_driver.hangup = rs_hangup;
serial_driver.break_ctl = rs_break;
serial_driver.wait_until_sent = rs_wait_until_sent;
serial_driver.read_proc = rs_read_proc;
/*
* Let's have a little bit of fun !
*/
for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
if (state->type == PORT_UNKNOWN) continue;
if (!state->irq) {
state->irq = ia64_alloc_irq();
ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
}
printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n",
state->line,
state->port, state->irq,
uart_config[state->type].name);
}
/*
* The callout device is just like normal device except for
* major number and the subtype code.
*/
callout_driver = serial_driver;
callout_driver.name = "cua";
callout_driver.major = TTYAUX_MAJOR;
callout_driver.subtype = SERIAL_TYPE_CALLOUT;
callout_driver.read_proc = 0;
callout_driver.proc_entry = 0;
if (tty_register_driver(&serial_driver))
panic("Couldn't register simserial driver\n");
if (tty_register_driver(&callout_driver))
panic("Couldn't register callout driver\n");
return 0;
}
#ifndef MODULE
__initcall(simrs_init);
#endif
#include <asm/asmmacro.h>
#include <asm/offsets.h>
#include <asm/signal.h>
#include <asm/thread_info.h>
#include "../kernel/minstate.h"
......@@ -87,18 +88,21 @@ END(sys32_sigsuspend)
GLOBAL_ENTRY(ia32_ret_from_clone)
PT_REGS_UNWIND_INFO(0)
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
/*
* We need to call schedule_tail() to complete the scheduling process.
* Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
* address of the previously executing task.
*/
br.call.sptk.many rp=ia64_invoke_schedule_tail
.ret1: adds r2=IA64_TASK_PTRACE_OFFSET,r13
.ret1:
#endif
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
;;
ld8 r2=[r2]
ld4 r2=[r2]
;;
mov r8=0
tbit.nz p6,p0=r2,PT_SYSCALLTRACE_BIT
tbit.nz p6,p0=r2,TIF_SYSCALL_TRACE
(p6) br.cond.spnt .ia32_strace_check_retval
;; // prevent RAW on r8
END(ia32_ret_from_clone)
......
......@@ -20,7 +20,7 @@ ia32_intercept (struct pt_regs *regs, unsigned long isr)
{
switch ((isr >> 16) & 0xff) {
case 0: /* Instruction intercept fault */
case 3: /* Locked Data reference fault */
case 4: /* Locked Data reference fault */
case 1: /* Gate intercept trap */
return -1;
......
......@@ -486,6 +486,7 @@ END(ia64_trace_syscall)
GLOBAL_ENTRY(ia64_ret_from_clone)
PT_REGS_UNWIND_INFO(0)
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
/*
* We need to call schedule_tail() to complete the scheduling process.
* Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
......@@ -493,6 +494,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
*/
br.call.sptk.many rp=ia64_invoke_schedule_tail
.ret8:
#endif
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
;;
ld4 r2=[r2]
......@@ -620,7 +622,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
shr.u r18=r19,16 // get byte size of existing "dirty" partition
;;
mov r16=ar.bsp // get existing backing store pointer
movl r17=PERCPU_ADDR+IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET
movl r17=THIS_CPU(ia64_phys_stacked_size_p8)
;;
ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8
(pKern) br.cond.dpnt skip_rbs_switch
......@@ -756,6 +758,7 @@ ENTRY(handle_syscall_error)
br.cond.sptk ia64_leave_kernel
END(handle_syscall_error)
#ifdef CONFIG_SMP
/*
* Invoke schedule_tail(task) while preserving in0-in7, which may be needed
* in case a system call gets restarted.
......@@ -772,6 +775,8 @@ GLOBAL_ENTRY(ia64_invoke_schedule_tail)
br.ret.sptk.many rp
END(ia64_invoke_schedule_tail)
#endif /* CONFIG_SMP */
#if __GNUC__ < 3
/*
......
......@@ -59,7 +59,7 @@ EXPORT_SYMBOL(clear_page);
#include <asm/processor.h>
# ifndef CONFIG_NUMA
EXPORT_SYMBOL(_cpu_data);
EXPORT_SYMBOL(cpu_info);
# endif
EXPORT_SYMBOL(kernel_thread);
......
......@@ -645,7 +645,6 @@ ENTRY(break_fault)
mov r3=255
adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024
adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = &current->ptrace
;;
cmp.geu p6,p7=r3,r15 // (syscall > 0 && syscall <= 1024+255) ?
movl r16=sys_call_table
......
......@@ -38,8 +38,8 @@
#ifdef CONFIG_PERFMON
/*
* For PMU which rely on the debug registers for some features, you must
* you must enable the following flag to activate the support for
* For PMUs which rely on the debug registers for some features, you
* must enable the following flag to activate the support for
* accessing the registers via the perfmonctl() interface.
*/
#ifdef CONFIG_ITANIUM
......@@ -313,6 +313,9 @@ static unsigned long pfm_spurious_ovfl_intr_count; /* keep track of spurious ovf
static unsigned long pfm_ovfl_intr_count; /* keep track of spurious ovfl interrupts */
static unsigned long pfm_recorded_samples_count;
static unsigned long reset_pmcs[IA64_NUM_PMC_REGS]; /* contains PAL reset values for PMCS */
static void pfm_vm_close(struct vm_area_struct * area);
static struct vm_operations_struct pfm_vm_ops={
close: pfm_vm_close
......@@ -331,7 +334,9 @@ static struct {
* forward declarations
*/
static void ia64_reset_pmu(struct task_struct *);
#ifdef CONFIG_SMP
static void pfm_fetch_regs(int cpu, struct task_struct *task, pfm_context_t *ctx);
#endif
static void pfm_lazy_save_regs (struct task_struct *ta);
static inline unsigned long
......@@ -422,7 +427,7 @@ pfm_rvfree(void *mem, unsigned long size)
if (mem) {
adr=(unsigned long) mem;
while ((long) size > 0)
while ((long) size > 0) {
mem_map_unreserve(vmalloc_to_page((void*)adr));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
......@@ -1500,11 +1505,12 @@ pfm_restart(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
*/
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
#if 0
if (ctx->ctx_fl_frozen==0) {
printk("task %d without pmu_frozen set\n", task->pid);
return -EINVAL;
}
#endif
if (task == current) {
DBprintk(("restarting self %d frozen=%d \n", current->pid, ctx->ctx_fl_frozen));
......@@ -1569,32 +1575,150 @@ pfm_restart(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
return 0;
}
#ifndef CONFIG_SMP
/*
* On UP kernels, we do not need to constantly set the psr.pp bit
* when a task is scheduled. The psr.pp bit can only be changed in
* the kernel because of a user request. Given we are on a UP non preeemptive
* kernel we know that no other task is running, so we cna simply update their
* psr.pp from their saved state. There is this no impact on the context switch
* code compared to the SMP case.
*/
static void
pfm_tasklist_toggle_pp(unsigned int val)
{
struct task_struct *p;
struct pt_regs *regs;
DBprintk(("invoked by [%d] pp=%u\n", current->pid, val));
read_lock(&tasklist_lock);
for_each_task(p) {
regs = (struct pt_regs *)((unsigned long) p + IA64_STK_OFFSET);
/*
* position on pt_regs saved on stack on 1st entry into the kernel
*/
regs--;
/*
* update psr.pp
*/
ia64_psr(regs)->pp = val;
}
read_unlock(&tasklist_lock);
}
#endif
static int
pfm_destroy_context(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
pfm_stop(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
struct pt_regs *regs)
{
/* we don't quite support this right now */
if (task != current) return -EINVAL;
if (ctx->ctx_fl_system) {
ia64_psr(regs)->pp = 0;
/*
* Cannot do anything before PMU is enabled
*/
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
DBprintk(("[%d] fl_system=%d owner=%p current=%p\n",
current->pid,
ctx->ctx_fl_system, PMU_OWNER(),
current));
/* simply stop monitoring but not the PMU */
if (ctx->ctx_fl_system) {
__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
/* disable dcr pp */
ia64_set_dcr(ia64_get_dcr() & ~IA64_DCR_PP);
#ifdef CONFIG_SMP
local_cpu_data->pfm_dcr_pp = 0;
#else
pfm_tasklist_toggle_pp(0);
#endif
ia64_psr(regs)->pp = 0;
} else {
ia64_psr(regs)->up = 0;
__asm__ __volatile__ ("rum psr.up;;"::: "memory");
task->thread.flags &= ~IA64_THREAD_PM_VALID;
ia64_psr(regs)->up = 0;
}
return 0;
}
SET_PMU_OWNER(NULL);
static int
pfm_disable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
struct pt_regs *regs)
{
/* we don't quite support this right now */
if (task != current) return -EINVAL;
/* freeze PMU */
ia64_set_pmc(0, 1);
ia64_srlz_d();
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
/*
* stop monitoring, freeze PMU, and save state in context
* this call will clear IA64_THREAD_PM_VALID for per-task sessions.
*/
pfm_flush_regs(task);
if (ctx->ctx_fl_system) {
ia64_psr(regs)->pp = 0;
} else {
ia64_psr(regs)->up = 0;
}
/*
* goes back to default behavior
* no need to change live psr.sp because useless at the kernel level
*/
ia64_psr(regs)->sp = 1;
DBprintk(("enabling psr.sp for [%d]\n", current->pid));
ctx->ctx_flags.state = PFM_CTX_DISABLED;
return 0;
}
static int
pfm_destroy_context(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
struct pt_regs *regs)
{
/* we don't quite support this right now */
if (task != current) return -EINVAL;
/*
* if context was never enabled, then there is not much
* to do
*/
if (!CTX_IS_ENABLED(ctx)) goto skipped_stop;
/*
* Disable context: stop monitoring, flush regs to software state (useless here),
* and freeze PMU
*
* The IA64_THREAD_PM_VALID is cleared by pfm_flush_regs() called from pfm_disable()
*/
pfm_disable(task, ctx, arg, count, regs);
if (ctx->ctx_fl_system) {
ia64_psr(regs)->pp = 0;
} else {
ia64_psr(regs)->up = 0;
}
/* restore security level */
ia64_psr(regs)->sp = 1;
skipped_stop:
/*
* remove sampling buffer mapping, if any
*/
......@@ -1910,8 +2034,13 @@ pfm_start(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
/* enable dcr pp */
ia64_set_dcr(ia64_get_dcr()|IA64_DCR_PP);
#ifdef CONFIG_SMP
local_cpu_data->pfm_dcr_pp = 1;
#else
pfm_tasklist_toggle_pp(1);
#endif
ia64_psr(regs)->pp = 1;
__asm__ __volatile__ ("ssm psr.pp;;"::: "memory");
} else {
......@@ -1985,80 +2114,6 @@ pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
return 0;
}
static int
pfm_disable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
struct pt_regs *regs)
{
/* we don't quite support this right now */
if (task != current) return -EINVAL;
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
/*
* stop monitoring, freeze PMU, and save state in context
*/
pfm_flush_regs(task);
/*
* just to make sure nothing starts again when back in user mode.
* pfm_flush_regs() freezes the PMU anyway.
*/
if (ctx->ctx_fl_system) {
ia64_psr(regs)->pp = 0;
} else {
ia64_psr(regs)->up = 0;
}
/*
* goes back to default behavior
* no need to change live psr.sp because useless at the kernel level
*/
ia64_psr(regs)->sp = 1;
DBprintk(("enabling psr.sp for [%d]\n", current->pid));
ctx->ctx_flags.state = PFM_CTX_DISABLED;
return 0;
}
static int
pfm_stop(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
struct pt_regs *regs)
{
/* we don't quite support this right now */
if (task != current) return -EINVAL;
/*
* Cannot do anything before PMU is enabled
*/
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
DBprintk(("[%d] fl_system=%d owner=%p current=%p\n",
current->pid,
ctx->ctx_fl_system, PMU_OWNER(),
current));
/* simply stop monitoring but not the PMU */
if (ctx->ctx_fl_system) {
__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
/* disable dcr pp */
ia64_set_dcr(ia64_get_dcr() & ~IA64_DCR_PP);
local_cpu_data->pfm_dcr_pp = 0;
ia64_psr(regs)->pp = 0;
__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
} else {
ia64_psr(regs)->up = 0;
__asm__ __volatile__ ("rum psr.up;;"::: "memory");
}
return 0;
}
/*
* functions MUST be listed in the increasing order of their index (see permfon.h)
*/
......@@ -2730,10 +2785,12 @@ perfmon_proc_info(char *page)
p += sprintf(p, "recorded samples=%lu\n", pfm_recorded_samples_count);
p += sprintf(p, "CPU%d.pmc[0]=%lx\nPerfmon debug: %s\n",
smp_processor_id(), pmc0, pfm_debug ? "On" : "Off");
smp_processor_id(), pmc0, pfm_debug_mode ? "On" : "Off");
#ifdef CONFIG_SMP
p += sprintf(p, "CPU%d cpu_data.pfm_syst_wide=%d cpu_data.dcr_pp=%d\n",
smp_processor_id(), local_cpu_data->pfm_syst_wide, local_cpu_data->pfm_dcr_pp);
#endif
LOCK_PFS();
p += sprintf(p, "proc_sessions=%lu\nsys_sessions=%lu\nsys_use_dbregs=%lu\nptrace_use_dbregs=%lu\n",
......@@ -2772,6 +2829,7 @@ perfmon_read_entry(char *page, char **start, off_t off, int count, int *eof, voi
return len;
}
#ifdef CONFIG_SMP
void
pfm_syst_wide_update_task(struct task_struct *task, int mode)
{
......@@ -2784,6 +2842,8 @@ pfm_syst_wide_update_task(struct task_struct *task, int mode)
*/
ia64_psr(regs)->pp = mode ? local_cpu_data->pfm_dcr_pp : 0;
}
#endif
void
pfm_save_regs (struct task_struct *task)
......@@ -2873,7 +2933,9 @@ pfm_lazy_save_regs (struct task_struct *task)
/* not owned by this CPU */
atomic_set(&ctx->ctx_last_cpu, -1);
#ifdef CONFIG_SMP
do_nothing:
#endif
/*
* declare we are done saving this context
*
......@@ -3010,7 +3072,10 @@ pfm_load_regs (struct task_struct *task)
struct task_struct *owner;
unsigned long mask;
u64 psr;
int i, cpu;
int i;
#ifdef CONFIG_SMP
int cpu;
#endif
owner = PMU_OWNER();
ctx = task->thread.pfm_context;
......@@ -3119,49 +3184,14 @@ pfm_load_regs (struct task_struct *task)
}
static void
pfm_model_specific_reset_pmu(struct task_struct *task)
{
int i;
#ifdef CONFIG_ITANIUM
/* opcode matcher set to all 1s */
ia64_set_pmc(8,~0UL);
ia64_set_pmc(9,~0UL);
/* I-EAR config cleared, plm=0 */
ia64_set_pmc(10,0UL);
/* D-EAR config cleared, PMC[11].pt must be 1 */
ia64_set_pmc(11,1UL << 28);
/* BTB config. plm=0 */
ia64_set_pmc(12,0UL);
/* Instruction address range, PMC[13].ta must be 1 */
ia64_set_pmc(13,1UL);
/*
* Clear all PMDs
*
* XXX: may be good enough to rely on the impl_regs to generalize
* this.
*/
for(i = 0; i< 18 ; i++) {
ia64_set_pmd(i,0UL);
}
#endif
}
/*
* XXX: this routine is not very portable for PMCs
* XXX: make this routine able to work with non current context
*/
static void
ia64_reset_pmu(struct task_struct *task)
{
pfm_context_t *ctx = task->thread.pfm_context;
struct thread_struct *t = &task->thread;
pfm_context_t *ctx = t->pfm_context;
unsigned long mask;
int i;
......@@ -3170,34 +3200,36 @@ ia64_reset_pmu(struct task_struct *task)
return;
}
/* PMU is frozen, no pending overflow bits */
/* Let's make sure the PMU is frozen */
ia64_set_pmc(0,1);
/*
* Let's first do the architected initializations
* install reset values for PMC. We skip PMC0 (done above)
* XX: good up to 64 PMCS
*/
/* clear counters */
ia64_set_pmd(4,0UL);
ia64_set_pmd(5,0UL);
ia64_set_pmd(6,0UL);
ia64_set_pmd(7,0UL);
/* clear overflow status bits */
ia64_set_pmc(1,0UL);
ia64_set_pmc(2,0UL);
ia64_set_pmc(3,0UL);
/* clear counting monitor configuration */
ia64_set_pmc(4,0UL);
ia64_set_pmc(5,0UL);
ia64_set_pmc(6,0UL);
ia64_set_pmc(7,0UL);
mask = pmu_conf.impl_regs[0] >> 1;
for(i=1; mask; mask>>=1, i++) {
if (mask & 0x1) {
ia64_set_pmc(i, reset_pmcs[i]);
/*
* When restoring context, we must restore ALL pmcs, even the ones
* that the task does not use to avoid leaks and possibly corruption
* of the sesion because of configuration conflicts. So here, we
* initializaed the table used in the context switch restore routine.
*/
t->pmc[i] = reset_pmcs[i];
DBprintk((" pmc[%d]=0x%lx\n", i, reset_pmcs[i]));
}
}
/*
* Now let's do the CPU model specific initializations
* clear reset values for PMD.
* XX: good up to 64 PMDS. Suppose that zero is a valid value.
*/
pfm_model_specific_reset_pmu(task);
mask = pmu_conf.impl_regs[4];
for(i=0; mask; mask>>=1, i++) {
if (mask & 0x1) ia64_set_pmd(i, 0UL);
}
/*
* On context switched restore, we must restore ALL pmc even
......@@ -3221,19 +3253,6 @@ ia64_reset_pmu(struct task_struct *task)
*/
ctx->ctx_reload_pmcs[0] = pmu_conf.impl_regs[0];
/*
* make sure we pick up whatever values were installed
* for the CPU model specific reset. We also include
* the architected PMC (pmc4-pmc7)
*
* This step is required in order to restore the correct values in PMC when
* the task is switched out and back in just after the PFM_ENABLE.
*/
mask = pmu_conf.impl_regs[0];
for (i=0; mask; i++, mask>>=1) {
if (mask & 0x1) t->pmc[i] = ia64_get_pmc(i);
}
/*
* useful in case of re-enable after disable
*/
......@@ -3280,14 +3299,18 @@ pfm_flush_regs (struct task_struct *task)
* By now, we could still have an overflow interrupt in-flight.
*/
if (ctx->ctx_fl_system) {
__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
/* disable dcr pp */
ia64_set_dcr(ia64_get_dcr() & ~IA64_DCR_PP);
#ifdef CONFIG_SMP
local_cpu_data->pfm_syst_wide = 0;
local_cpu_data->pfm_dcr_pp = 0;
__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
#else
pfm_tasklist_toggle_pp(0);
#endif
} else {
......@@ -3386,6 +3409,7 @@ pfm_flush_regs (struct task_struct *task)
}
/*
* task is the newly created task, pt_regs for new child
*/
......@@ -3803,6 +3827,17 @@ static struct irqaction perfmon_irqaction = {
};
static void
pfm_pmu_snapshot(void)
{
int i;
for (i=0; i < IA64_NUM_PMC_REGS; i++) {
if (i >= pmu_conf.num_pmcs) break;
if (PMC_IS_IMPL(i)) reset_pmcs[i] = ia64_get_pmc(i);
}
}
/*
* perfmon initialization routine, called from the initcall() table
*/
......@@ -3836,8 +3871,7 @@ perfmon_init (void)
pmu_conf.num_pmcs = find_num_pm_regs(pmu_conf.impl_regs);
pmu_conf.num_pmds = find_num_pm_regs(&pmu_conf.impl_regs[4]);
printk("perfmon: %u bits counters (max value 0x%016lx)\n",
pm_info.pal_perf_mon_info_s.width, pmu_conf.perf_ovfl_val);
printk("perfmon: %u bits counters\n", pm_info.pal_perf_mon_info_s.width);
printk("perfmon: %lu PMC/PMD pairs, %lu PMCs, %lu PMDs\n",
pmu_conf.max_counters, pmu_conf.num_pmcs, pmu_conf.num_pmds);
......@@ -3856,6 +3890,19 @@ perfmon_init (void)
pmu_conf.num_ibrs <<=1;
pmu_conf.num_dbrs <<=1;
/*
* take a snapshot of all PMU registers. PAL is supposed
* to configure them with stable/safe values, i.e., not
* capturing anything.
* We take a snapshot now, before we make any modifications. This
* will become our master copy. Then we will reuse the snapshot
* to reset the PMU in pfm_enable(). Using this technique, perfmon
* does NOT have to know about the specific values to program for
* the PMC/PMD. The safe values may be different from one CPU model to
* the other.
*/
pfm_pmu_snapshot();
/*
* list the pmc registers used to control monitors
* XXX: unfortunately this information is not provided by PAL
......
......@@ -193,7 +193,10 @@ ia64_save_extra (struct task_struct *task)
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
pfm_save_regs(task);
if (local_cpu_data->pfm_syst_wide) pfm_syst_wide_update_task(task, 0);
# ifdef CONFIG_SMP
if (local_cpu_data->pfm_syst_wide)
pfm_syst_wide_update_task(task, 0);
# endif
#endif
if (IS_IA32_PROCESS(ia64_task_regs(task)))
......@@ -210,7 +213,9 @@ ia64_load_extra (struct task_struct *task)
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
pfm_load_regs(task);
# ifdef CONFIG_SMP
if (local_cpu_data->pfm_syst_wide) pfm_syst_wide_update_task(task, 1);
# endif
#endif
if (IS_IA32_PROCESS(ia64_task_regs(task)))
......
......@@ -54,12 +54,10 @@
extern char _end;
#ifdef CONFIG_NUMA
struct cpuinfo_ia64 *boot_cpu_data;
#else
struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));
#endif
unsigned long __per_cpu_offset[NR_CPUS];
struct cpuinfo_ia64 cpu_info __per_cpu_data;
unsigned long ia64_phys_stacked_size_p8;
unsigned long ia64_cycles_per_usec;
struct ia64_boot_param *ia64_boot_param;
struct screen_info screen_info;
......@@ -511,6 +509,12 @@ identify_cpu (struct cpuinfo_ia64 *c)
c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
}
void
setup_per_cpu_areas (void)
{
/* start_kernel() requires this... */
}
/*
* cpu_init() initializes state that is per-CPU. This function acts
* as a 'CPU state barrier', nothing should get across.
......@@ -518,46 +522,21 @@ identify_cpu (struct cpuinfo_ia64 *c)
void
cpu_init (void)
{
extern char __per_cpu_start[], __phys_per_cpu_start[], __per_cpu_end[];
extern void __init ia64_mmu_init (void *);
unsigned long num_phys_stacked;
pal_vm_info_2_u_t vmi;
unsigned int max_ctx;
struct cpuinfo_ia64 *my_cpu_data;
#ifdef CONFIG_NUMA
int cpu, order;
struct cpuinfo_ia64 *my_cpu_info;
void *my_cpu_data;
int cpu = smp_processor_id();
/*
* If NUMA is configured, the cpu_data array is not preallocated. The boot cpu
* allocates entries for every possible cpu. As the remaining cpus come online,
* they reallocate a new cpu_data structure on their local node. This extra work
* is required because some boot code references all cpu_data structures
* before the cpus are actually started.
*/
if (!boot_cpu_data) {
my_cpu_data = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
sizeof(struct cpuinfo_ia64));
boot_cpu_data = my_cpu_data;
my_cpu_data->cpu_data[0] = my_cpu_data;
for (cpu = 1; cpu < NR_CPUS; ++cpu)
my_cpu_data->cpu_data[cpu]
= alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
sizeof(struct cpuinfo_ia64));
for (cpu = 1; cpu < NR_CPUS; ++cpu)
memcpy(my_cpu_data->cpu_data[cpu]->cpu_data,
my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data));
} else {
order = get_order(sizeof(struct cpuinfo_ia64));
my_cpu_data = page_address(alloc_pages_node(numa_node_id(), GFP_KERNEL, order));
memcpy(my_cpu_data, boot_cpu_data->cpu_data[smp_processor_id()],
sizeof(struct cpuinfo_ia64));
__free_pages(virt_to_page(boot_cpu_data->cpu_data[smp_processor_id()]),
order);
for (cpu = 0; cpu < NR_CPUS; ++cpu)
boot_cpu_data->cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
}
#else
my_cpu_data = cpu_data(smp_processor_id());
#endif
my_cpu_data = alloc_bootmem_pages(__per_cpu_end - __per_cpu_start);
memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
__per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start;
my_cpu_info = my_cpu_data + ((char *) &cpu_info - __per_cpu_start);
/*
* We can't pass "local_cpu_data" to identify_cpu() because we haven't called
......@@ -565,7 +544,7 @@ cpu_init (void)
* depends on the data returned by identify_cpu(). We break the dependency by
* accessing cpu_data() the old way, through identity mapped space.
*/
identify_cpu(my_cpu_data);
identify_cpu(my_cpu_info);
/* Clear the stack memory reserved for pt_regs: */
memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
......@@ -626,7 +605,7 @@ cpu_init (void)
printk ("cpu_init: PAL RSE info failed, assuming 96 physical stacked regs\n");
num_phys_stacked = 96;
}
local_cpu_data->phys_stacked_size_p8 = num_phys_stacked*8 + 8;
/* size of physical stacked register partition plus 8 bytes: */
ia64_phys_stacked_size_p8 = num_phys_stacked*8 + 8;
platform_cpu_init();
}
......@@ -75,12 +75,11 @@ struct call_data_struct {
static volatile struct call_data_struct *call_data;
static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
static task_t *migrating_task;
#define IPI_CALL_FUNC 0
#define IPI_CPU_STOP 1
#define IPI_MIGRATE_TASK 2
/* This needs to be cacheline aligned because it is written to by *other* CPUs. */
static __u64 ipi_operation __per_cpu_data ____cacheline_aligned;
static void
stop_this_cpu (void)
......@@ -99,7 +98,7 @@ void
handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
{
int this_cpu = smp_processor_id();
unsigned long *pending_ipis = &local_cpu_data->ipi_operation;
unsigned long *pending_ipis = &this_cpu(ipi_operation);
unsigned long ops;
/* Count this now; we may make a call that never returns. */
......@@ -143,14 +142,6 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
}
break;
case IPI_MIGRATE_TASK:
{
task_t *p = migrating_task;
spin_unlock(&migration_lock);
sched_task_migrated(p);
}
break;
case IPI_CPU_STOP:
stop_this_cpu();
break;
......@@ -167,7 +158,7 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
static inline void
send_IPI_single (int dest_cpu, int op)
{
set_bit(op, &cpu_data(dest_cpu)->ipi_operation);
set_bit(op, &per_cpu(ipi_operation, dest_cpu));
platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
}
......@@ -350,15 +341,6 @@ smp_send_stop (void)
smp_num_cpus = 1;
}
void
smp_migrate_task (int cpu, task_t *p)
{
/* The target CPU will unlock the migration spinlock: */
spin_lock(&migration_lock);
migrating_task = p;
send_IPI_single(cpu, IPI_MIGRATE_TASK);
}
int __init
setup_profiling_timer (unsigned int multiplier)
{
......
......@@ -1305,11 +1305,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
* handler into reading an arbitrary kernel addresses...
*/
if (!user_mode(regs)) {
#ifdef GAS_HAS_LOCAL_TAGS
fix = search_exception_table(regs->cr_iip + ia64_psr(regs)->ri);
#else
fix = search_exception_table(regs->cr_iip);
#endif
fix = SEARCH_EXCEPTION_TABLE(regs);
}
if (user_mode(regs) || fix.cont) {
if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0)
......
......@@ -18,7 +18,7 @@
# define PREFETCH_LINES 9 // magic number
#else
# define L3_LINE_SIZE 128 // McKinley L3 line size
# define PREFETCH_LINES 7 // magic number
# define PREFETCH_LINES 12 // magic number
#endif
#define saved_lc r2
......
......@@ -49,7 +49,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
int signal = SIGSEGV, code = SEGV_MAPERR;
struct vm_area_struct *vma, *prev_vma;
struct mm_struct *mm = current->mm;
struct exception_fixup fix;
struct siginfo si;
unsigned long mask;
......@@ -167,15 +166,8 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
return;
}
#ifdef GAS_HAS_LOCAL_TAGS
fix = search_exception_table(regs->cr_iip + ia64_psr(regs)->ri);
#else
fix = search_exception_table(regs->cr_iip);
#endif
if (fix.cont) {
handle_exception(regs, fix);
if (done_with_exception(regs))
return;
}
/*
* Oops. The kernel tried to access some bad page. We'll have to terminate things
......
......@@ -103,12 +103,12 @@ free_initmem (void)
free_page(addr);
++totalram_pages;
}
printk ("Freeing unused kernel memory: %ldkB freed\n",
(&__init_end - &__init_begin) >> 10);
printk(KERN_INFO "Freeing unused kernel memory: %ldkB freed\n",
(&__init_end - &__init_begin) >> 10);
}
void
free_initrd_mem(unsigned long start, unsigned long end)
free_initrd_mem (unsigned long start, unsigned long end)
{
/*
* EFI uses 4KB pages while the kernel can use 4KB or bigger.
......@@ -145,7 +145,7 @@ free_initrd_mem(unsigned long start, unsigned long end)
end = end & PAGE_MASK;
if (start < end)
printk ("Freeing initrd memory: %ldkB freed\n", (end - start) >> 10);
printk(KERN_INFO "Freeing initrd memory: %ldkB freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
if (!VALID_PAGE(virt_to_page(start)))
......
......@@ -7,12 +7,6 @@ BEGIN {
print " * This file was generated by arch/ia64/tools/print_offsets.awk."
print " *"
print " */"
#
# This is a cheesy hack. Make sure that
# PT_PTRACED == 1<<PT_PTRACED_BIT.
#
print "#define PT_PTRACED_BIT 0"
print "#define PT_SYSCALLTRACE_BIT 1"
}
# look for .tab:
......
......@@ -52,14 +52,7 @@ tab[] =
{ "SIGFRAME_SIZE", sizeof (struct sigframe) },
{ "UNW_FRAME_INFO_SIZE", sizeof (struct unw_frame_info) },
{ "", 0 }, /* spacer */
{ "IA64_TASK_PTRACE_OFFSET", offsetof (struct task_struct, ptrace) },
{ "IA64_TASK_THREAD_OFFSET", offsetof (struct task_struct, thread) },
{ "IA64_TASK_THREAD_KSP_OFFSET", offsetof (struct task_struct, thread.ksp) },
#ifdef CONFIG_PERFMON
{ "IA64_TASK_PFM_OVFL_BLOCK_RESET_OFFSET",offsetof(struct task_struct, thread.pfm_ovfl_block_reset) },
#endif
{ "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) },
{ "IA64_TASK_MM_OFFSET", offsetof (struct task_struct, mm) },
{ "IA64_PT_REGS_CR_IPSR_OFFSET", offsetof (struct pt_regs, cr_ipsr) },
{ "IA64_PT_REGS_CR_IIP_OFFSET", offsetof (struct pt_regs, cr_iip) },
{ "IA64_PT_REGS_CR_IFS_OFFSET", offsetof (struct pt_regs, cr_ifs) },
......@@ -169,9 +162,6 @@ tab[] =
{ "IA64_SIGFRAME_SIGCONTEXT_OFFSET", offsetof (struct sigframe, sc) },
{ "IA64_CLONE_VFORK", CLONE_VFORK },
{ "IA64_CLONE_VM", CLONE_VM },
{ "IA64_CPU_IRQ_COUNT_OFFSET", offsetof (struct cpuinfo_ia64, irq_stat.f.irq_count) },
{ "IA64_CPU_BH_COUNT_OFFSET", offsetof (struct cpuinfo_ia64, irq_stat.f.bh_count) },
{ "IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET",offsetof (struct cpuinfo_ia64, phys_stacked_size_p8)},
};
static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
......@@ -189,16 +179,6 @@ main (int argc, char **argv)
printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by "
"arch/ia64/tools/print_offsets.\n *\n */\n\n");
/* This is stretching things a bit, but entry.S needs the bit number
for PT_PTRACED and it can't include <linux/sched.h> so this seems
like a reasonably solution. At least the code won't break in
subtle ways should PT_PTRACED ever change. Ditto for
PT_TRACESYS_BIT. */
printf ("#define PT_PTRACED_BIT\t\t\t%u\n", ffs (PT_PTRACED) - 1);
#if 0
printf ("#define PT_SYSCALLTRACE_BIT\t\t\t%u\n\n", ffs (PT_SYSCALLTRACE) - 1);
#endif
for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i)
{
if (tab[i].name[0] == '\0')
......
#include <linux/config.h>
#include <asm/cache.h>
#include <asm/ptrace.h>
#include <asm/system.h>
......@@ -70,11 +71,6 @@ SECTIONS
{ *(__ksymtab) }
__stop___ksymtab = .;
__start___kallsyms = .; /* All kernel symbols for debugging */
__kallsyms : AT(ADDR(__kallsyms) - PAGE_OFFSET)
{ *(__kallsyms) }
__stop___kallsyms = .;
/* Unwind info & table: */
. = ALIGN(8);
.IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - PAGE_OFFSET)
......@@ -124,10 +120,7 @@ SECTIONS
.data.init_task : AT(ADDR(.data.init_task) - PAGE_OFFSET)
{ *(.data.init_task) }
.data.page_aligned : AT(ADDR(.data.page_aligned) - PAGE_OFFSET)
{ *(.data.idt) }
. = ALIGN(64);
. = ALIGN(SMP_CACHE_BYTES);
.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - PAGE_OFFSET)
{ *(.data.cacheline_aligned) }
......@@ -135,6 +128,17 @@ SECTIONS
.kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET)
{ *(.kstrtab) }
/* Per-cpu data: */
. = ALIGN(PAGE_SIZE);
__phys_per_cpu_start = .;
.data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - PAGE_OFFSET)
{
__per_cpu_start = .;
*(.data.percpu)
__per_cpu_end = .;
}
. = __phys_per_cpu_start + 4096; /* ensure percpu fits into smallest page size (4KB) */
.data : AT(ADDR(.data) - PAGE_OFFSET)
{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
......@@ -151,7 +155,7 @@ SECTIONS
{ *(.sbss) *(.scommon) }
.bss : AT(ADDR(.bss) - PAGE_OFFSET)
{ *(.bss) *(COMMON) }
. = ALIGN(64 / 8);
_end = .;
/* Stabs debugging sections. */
......
......@@ -9,6 +9,8 @@
* scheduler patch
*/
#include <linux/types.h>
#include <asm/system.h>
/**
......@@ -97,7 +99,7 @@ clear_bit (int nr, volatile void *addr)
static __inline__ void
__clear_bit (int nr, volatile void *addr)
{
volatile __u32 *p = (__u32 *) addr + (nr >> 5);;
volatile __u32 *p = (__u32 *) addr + (nr >> 5);
__u32 m = 1 << (nr & 31);
*p &= ~m;
}
......
......@@ -5,7 +5,7 @@
/*
* Copyright (C) 1998-2000 Hewlett-Packard Co
* Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
/* Bytes per L1 (data) cache line. */
......
......@@ -2,8 +2,8 @@
#define _ASM_IA64_HARDIRQ_H
/*
* Copyright (C) 1998-2001 Hewlett-Packard Co
* Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>
......
......@@ -9,6 +9,7 @@
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
#define PROT_SEM 0x8 /* page may be used for atomic ops */
#define PROT_NONE 0x0 /* page can not be accessed */
#define MAP_SHARED 0x01 /* Share changes */
......
......@@ -6,23 +6,16 @@
* This file was generated by arch/ia64/tools/print_offsets.awk.
*
*/
#define PT_PTRACED_BIT 0
#define PT_SYSCALLTRACE_BIT 1
#define IA64_TASK_SIZE 3936 /* 0xf60 */
#define IA64_THREAD_INFO_SIZE 24 /* 0x18 */
#define IA64_PT_REGS_SIZE 400 /* 0x190 */
#define IA64_SWITCH_STACK_SIZE 560 /* 0x230 */
#define IA64_SIGINFO_SIZE 128 /* 0x80 */
#define IA64_CPU_SIZE 16384 /* 0x4000 */
#define IA64_CPU_SIZE 224 /* 0xe0 */
#define SIGFRAME_SIZE 2816 /* 0xb00 */
#define UNW_FRAME_INFO_SIZE 448 /* 0x1c0 */
#define IA64_TASK_PTRACE_OFFSET 32 /* 0x20 */
#define IA64_TASK_THREAD_OFFSET 1472 /* 0x5c0 */
#define IA64_TASK_THREAD_KSP_OFFSET 1480 /* 0x5c8 */
#define IA64_TASK_PFM_OVFL_BLOCK_RESET_OFFSET 2096 /* 0x830 */
#define IA64_TASK_PID_OFFSET 212 /* 0xd4 */
#define IA64_TASK_MM_OFFSET 136 /* 0x88 */
#define IA64_PT_REGS_CR_IPSR_OFFSET 0 /* 0x0 */
#define IA64_PT_REGS_CR_IIP_OFFSET 8 /* 0x8 */
#define IA64_PT_REGS_CR_IFS_OFFSET 16 /* 0x10 */
......@@ -132,8 +125,5 @@
#define IA64_SIGFRAME_SIGCONTEXT_OFFSET 160 /* 0xa0 */
#define IA64_CLONE_VFORK 16384 /* 0x4000 */
#define IA64_CLONE_VM 256 /* 0x100 */
#define IA64_CPU_IRQ_COUNT_OFFSET 0 /* 0x0 */
#define IA64_CPU_BH_COUNT_OFFSET 4 /* 0x4 */
#define IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET 12 /* 0xc */
#endif /* _ASM_IA64_OFFSETS_H */
......@@ -15,6 +15,8 @@
#include <linux/config.h>
#include <linux/compiler.h>
#include <asm/ptrace.h>
#include <asm/kregs.h>
#include <asm/system.h>
......@@ -184,6 +186,10 @@
*/
#define IA64_USEC_PER_CYC_SHIFT 41
#define __HAVE_ARCH_PER_CPU
#define THIS_CPU(var) (var)
#ifndef __ASSEMBLY__
#include <linux/threads.h>
......@@ -196,6 +202,11 @@
#include <asm/unwind.h>
#include <asm/atomic.h>
extern unsigned long __per_cpu_offset[NR_CPUS];
#define per_cpu(var, cpu) (*(__typeof__(&(var))) ((void *) &(var) + __per_cpu_offset[cpu]))
#define this_cpu(var) (var)
/* like above but expressed as bitfields for more efficient access: */
struct ia64_psr {
__u64 reserved0 : 1;
......@@ -239,7 +250,7 @@ struct ia64_psr {
* CPU type, hardware bug flags, and per-CPU state. Frequently used
* state comes earlier:
*/
struct cpuinfo_ia64 {
extern struct cpuinfo_ia64 {
/* irq_stat must be 64-bit aligned */
union {
struct {
......@@ -249,7 +260,6 @@ struct cpuinfo_ia64 {
__u64 irq_and_bh_counts;
} irq_stat;
__u32 softirq_pending;
__u32 phys_stacked_size_p8; /* size of physical stacked registers + 8 */
__u64 itm_delta; /* # of clock cycles between clock ticks */
__u64 itm_next; /* interval timer mask value to use for next clock tick */
__u64 *pgd_quick;
......@@ -282,41 +292,15 @@ struct cpuinfo_ia64 {
__u64 prof_multiplier;
__u32 pfm_syst_wide;
__u32 pfm_dcr_pp;
/* this is written to by *other* CPUs: */
__u64 ipi_operation ____cacheline_aligned;
#endif
#ifdef CONFIG_NUMA
void *node_directory;
int numa_node_id;
struct cpuinfo_ia64 *cpu_data[NR_CPUS];
#endif
/* Platform specific word. MUST BE LAST IN STRUCT */
__u64 platform_specific;
} __attribute__ ((aligned (PAGE_SIZE))) ;
} cpu_info __per_cpu_data;
/*
* The "local" data pointer. It points to the per-CPU data of the currently executing
* CPU, much like "current" points to the per-task data of the currently executing task.
*/
#define local_cpu_data ((struct cpuinfo_ia64 *) PERCPU_ADDR)
/*
* On NUMA systems, cpu_data for each cpu is allocated during cpu_init() & is allocated on
* the node that contains the cpu. This minimizes off-node memory references. cpu_data
* for each cpu contains an array of pointers to the cpu_data structures of each of the
* other cpus.
*
* On non-NUMA systems, cpu_data is a static array allocated at compile time. References
* to the cpu_data of another cpu is done by direct references to the appropriate entry of
* the array.
*/
#ifdef CONFIG_NUMA
# define cpu_data(cpu) local_cpu_data->cpu_data[cpu]
# define numa_node_id() (local_cpu_data->numa_node_id)
#else
extern struct cpuinfo_ia64 _cpu_data[NR_CPUS];
# define cpu_data(cpu) (&_cpu_data[cpu])
#endif
#define local_cpu_data (&this_cpu(cpu_info))
#define cpu_data(cpu) (&per_cpu(cpu_info, cpu))
extern void identify_cpu (struct cpuinfo_ia64 *);
extern void print_cpu_info (struct cpuinfo_ia64 *);
......
......@@ -136,6 +136,7 @@ typedef struct siginfo {
#define SI_ASYNCIO (-4) /* sent by AIO completion */
#define SI_SIGIO (-5) /* sent by queued SIGIO */
#define SI_TKILL (-6) /* sent by tkill system call */
#define SI_DETHREAD (-7) /* sent by execve() killing subsidiary threads */
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
......
......@@ -12,30 +12,36 @@
extern spinlock_t kernel_flag;
#define kernel_locked() spin_is_locked(&kernel_flag)
#ifdef CONFIG_SMP
# define kernel_locked() spin_is_locked(&kernel_flag)
# define check_irq_holder(cpu) \
do { \
if (global_irq_holder == (cpu)) \
BUG(); \
} while (0)
#else
# define kernel_locked() (1)
#endif
/*
* Release global kernel lock and global interrupt lock
*/
static __inline__ void
release_kernel_lock(struct task_struct *task, int cpu)
{
if (unlikely(task->lock_depth >= 0)) {
spin_unlock(&kernel_flag);
if (global_irq_holder == (cpu)) \
BUG(); \
}
}
#define release_kernel_lock(task, cpu) \
do { \
if (unlikely(task->lock_depth >= 0)) { \
spin_unlock(&kernel_flag); \
check_irq_holder(cpu); \
} \
} while (0)
/*
* Re-acquire the kernel lock
*/
static __inline__ void
reacquire_kernel_lock(struct task_struct *task)
{
if (unlikely(task->lock_depth >= 0))
spin_lock(&kernel_flag);
}
#define reacquire_kernel_lock(task) \
do { \
if (unlikely(task->lock_depth >= 0)) \
spin_lock(&kernel_flag); \
} while (0)
/*
* Getting the big kernel lock.
......
......@@ -397,13 +397,17 @@ extern void ia64_load_extra (struct task_struct *task);
} while (0)
#ifdef CONFIG_SMP
/*
* In the SMP case, we save the fph state when context-switching
* away from a thread that modified fph. This way, when the thread
* gets scheduled on another CPU, the CPU can pick up the state from
* task->thread.fph, avoiding the complication of having to fetch
* the latest fph state from another CPU.
*/
/* Return true if this CPU can call the console drivers in printk() */
#define arch_consoles_callable() (cpu_online_map & (1UL << smp_processor_id()))
/*
* In the SMP case, we save the fph state when context-switching
* away from a thread that modified fph. This way, when the thread
* gets scheduled on another CPU, the CPU can pick up the state from
* task->thread.fph, avoiding the complication of having to fetch
* the latest fph state from another CPU.
*/
# define switch_to(prev,next) do { \
if (ia64_psr(ia64_task_regs(prev))->mfh) { \
ia64_psr(ia64_task_regs(prev))->mfh = 0; \
......
......@@ -320,4 +320,22 @@ struct exception_fixup {
extern struct exception_fixup search_exception_table (unsigned long addr);
extern void handle_exception (struct pt_regs *regs, struct exception_fixup fixup);
#ifdef GAS_HAS_LOCAL_TAGS
#define SEARCH_EXCEPTION_TABLE(regs) search_exception_table(regs->cr_iip + ia64_psr(regs)->ri);
#else
#define SEARCH_EXCEPTION_TABLE(regs) search_exception_table(regs->cr_iip);
#endif
static inline int
done_with_exception (struct pt_regs *regs)
{
struct exception_fixup fix;
fix = SEARCH_EXCEPTION_TABLE(regs);
if (fix.cont) {
handle_exception(regs, fix);
return 1;
}
return 0;
}
#endif /* _ASM_IA64_UACCESS_H */
......@@ -1452,8 +1452,10 @@ void __init init_idle(task_t *idle, int cpu)
set_tsk_need_resched(idle);
__restore_flags(flags);
#ifdef CONFIG_PREEMPT
/* Set the preempt count _outside_ the spinlocks! */
idle->thread_info->preempt_count = (idle->lock_depth >= 0);
#endif
}
extern void init_timervecs(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment